Java集合(collections)框架提供了一组接口和类,以实现各种数据结构和算法。例如,集合框架的LinkedList类提供了双向链接列表数据结构的实现。
Collection 接口 Collection
接口是集合框架的root
根接口.
Java
不提供Collection
接口的直接实现,但是提供其子接口(如List
,Set
和Queue
)的实现。
Collections 框架 Vs. Collection 接口 人们会对 Collections框架
和Collection接口
感到迷惑.
Collection接口
是collections框架
的根接口。该框架还包括其他接口:Map
和Iterator
,这些接口也可以具有子接口。
Collections接口的子接口 如前所述,Collection接口
包括由Java类
实现的子接口。
Collection接口
的所有方法也都存在于其子接口中。
这是收集接口的子接口:
List Interface List接口
是一个有序的集合,它允许我们添加和删除数组之类的元素。
Set Interface Set接口
允许我们将元素存储在不同的集合中,类似于数学中的集合。它不能有重复的元素。
Queue Interface 当我们要以First In, First Out(FIFO)
(先进先出)的方式存储和访问元素时,可以使用Queue接口
。
Map Interface 在Java中,Map接口允许将元素存储在key/value
对中。key
是唯一的名称,可用于访问Map
中的特定元素。
Iterator Interface 在Java中,Iterator接口
提供了可用于访问集合元素的方法。
为什么用 Collections 框架 Java集合框架提供了可以直接使用的各种数据结构和算法。这有两个主要优点:
我们不必编写代码即可手动实现这些数据结构和算法。
随着集合框架的高度优化,我们的代码将更加高效。
此外,集合框架允许我们对特定类型的数据使用特定的数据结构。这里有一些例子:
如果我们希望数据唯一,则可以使用collections框架
提供的Set接口
。
要将数据存储在key/value
对中,我们可以使用Map接口
。
ArrayList
类提供可调整大小的数组的功能。
Collections例子: ArrayList Class ArrayList
类允许我们创建可调整大小的数组。该类实现List
接口(这是Collection接口
的子接口)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> animals = new ArrayList<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayList: " + animals); } }
输出:
1 ArrayList: [Dog, Cat, Horse]
Collection 中的方法 Collection接口包括各种方法,可用于对对象执行不同的操作.这些方法在其所有子接口中均可用。
add()
- 将指定的元素插入到集合中
size()
- 返回集合的大小
remove()
- 从集合中删除指定的元素
iterator()
- 返回用于访问集合元素的迭代器
addAll()
- 将指定集合的所有元素添加到集合中
removeAll()
- 从集合中删除指定集合的所有元素
clear()
- 删除集合的所有元素
在Java中,List接口
是一个有序的集合,允许我们按顺序存储和访问元素。它扩展了Collection接口
。
实现List
接口的类 由于List
是一个接口,因此我们无法从中创建对象。 为了使用List接口的功能,我们可以使用以下类:
这些类在Collections框架中定义,并实现List接口
。
如何使用List 在Java中,必须导入java.util.List
包才能使用List
。
1 2 3 4 5 List<String> list1 = new ArrayList<>(); List<String> list2 = new LinkedList<>();
在这里,我们创建了ArrayList
和LinkedList
类的对象list1
和list2
。这些对象可以使用List
接口的功能。
List 中的方法 List
接口包括Collection
接口的所有方法。这是因为Collection
是List
的父级接口。
List
接口中还提供了Collection
接口的一些常用方法:
add()
- 向list
添加一个元素.
addAll()
- 将一个列表中的所有元素添加进另一个列表中.
get()
- 帮助随机访问列表中的元素.
iterator()
- 返回可用于顺序访问列表元素的迭代器对象.
set()
- 更改列表元素.
remove()
- 从列表中删除一个元素.
removeAll()
- 从列表中删除所有元素.
clear()
- 从列表中删除所有元素(比removeAll()更有效).
size()
- 返回列表的长度.
toArray()
- 将列表转换为数组.
contains()
- 如果列表包含指定的元素,则返回true.
List 接口的实现 ArrayList
类实现1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.List;import java.util.ArrayList;class Main { public static void main (String[] args) { List<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("List: " + numbers); int number = numbers.get(2 ); System.out.println("Accessed Element: " + number); int removedNumber = numbers.remove(1 ); System.out.println("Removed Element: " + removedNumber); } }
输出:
1 2 3 List: [1 , 2 , 3 ] Accessed Element: 3 Removed Element: 2
LinkedList
类实现1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.List;import java.util.LinkedList;class Main { public static void main (String[] args) { List<Integer> numbers = new LinkedList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("List: " + numbers); int number = numbers.get(2 ); System.out.println("Accessed Element: " + number); int index = numbers.indexOf(2 ); System.out.println("Position of 3 is " + index); int removedNumber = numbers.remove(1 ); System.out.println("Removed Element: " + removedNumber); } }
输出:
1 2 3 4 List: [1 , 2 , 3 ] Accessed Element: 3 Position of 3 is 1 Removed Element: 2
Java List
VS Set
List接口和Set接口都继承了Collection接口。但是,它们之间存在一些差异。
List
可以包含重复的元素。但是,Set`不能有重复的元素。
List
中的元素以某种顺序存储。但是,Set
中的元素像数学中的集合一样按组存储。
ArrayList
类,在Java集合框架中提供了可以调整数组大小功能.
ArrayList Vs Array 在Java中, 我们需要先声明数组
的大小,再使用它.当数组
的大小一旦定义,你就很难去改变它.
为了解决这个问题,我们可以使用ArrayList
,它允许我们创建可调整大小的数组。
ArrayList
会自动的在我们新增或删除元素的时候动态调整它的大小.因此ArrayList
也被称为动态数组
.
创建 一个ArrayList 在使用ArrayList
之前,我们需要首先导入java.util.ArrayList
包。
创建arraylist
语法:
1 ArrayList<Type> arrayList= new ArrayList<>();
Type
表示arrayList
中元素类型.
1 2 3 4 5 ArrayList<Integer> arrayList = new ArrayList<>(); ArrayList<String> arrayList = new ArrayList<>();
在上面的程序中,我们使用了Integer
并不能进行初始化。这是因为我们在创建arraylist时不能使用基本类型。我们应该使用相应的包装器类 。
例子🌰 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("Swift" ); System.out.println("ArrayList: " + languages); } }
输出:
1 ArrayList: [Java, Python, Swift]
在上面的示例中,我们创建了一个名为language
的ArrayList
。
在这里,我们使用了add()
方法将元素添加到arraylist
中。
我们还可以使用List
接口创建一个arraylist。这是因为ArrayList类实现了List接口。
1 List<String> list = new ArrayList<>();
ArrayList 基本操作 ArrayList
提供了各种对arraylist
操作的方法.
添加元素到 ArrayList 要将单个元素添加到arraylist
,我们使用ArrayList
类的add()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("C" ); languages.add("Python" ); System.out.println("ArrayList: " + languages); languages.add(1 , "JavaScript" ); System.out.println("Updated ArrayList: " + languages); } }
输出:
1 2 ArrayList: [Java, C, Python] Updated ArrayList: [Java, JavaScript, C, Python]
在上面的示例中,我们创建了一个名为language
的ArrayList
。在这里,我们使用add()
方法将元素添加到语言中。
注意声明:
1 languages.add(1 , "JavaScript" );
在这里,我们使用了索引号参数。它是一个可选参数,用于指定添加新元素的位置。
获取ArrayList中一个元素 要访问arraylist
中的元素,我们使用ArrayList
类的get()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> animals = new ArrayList<>(); animals.add("Cat" ); animals.add("Dog" ); animals.add("Cow" ); System.out.println("ArrayList: " + animals); String str = animals.get(1 ); System.out.print("Element at index 1: " + str); } }
输出
1 2 ArrayList: [Cat, Dog, Cow] Element at index 1 : Dog
在上面的示例中,我们使用了带有参数1
的get()
方法。这里,该方法返回索引为1
的元素。
修改ArrayList中的元素 要更改arraylist的元素,我们使用ArrayList
类的set()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("Kotlin" ); languages.add("C++" ); System.out.println("ArrayList: " + languages); languages.set(2 , "JavaScript" ); System.out.println("Modified ArrayList: " + languages); } }
输出:
1 2 ArrayList: [Java, Kotlin, C++] Modified ArrayList: [Java, Kotlin, JavaScript]
在上面的示例中,我们创建了一个名为language
的ArrayList。但是通过language.set(2,'JavaScript')
.我们修改了下标2
的元素值为JavaScript
.
移除ArrayList中元素 要从arraylist中删除一个元素,我们可以使用ArrayList
类的remove()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> animals = new ArrayList<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayList: " + animals); String str = animals.remove(2 ); System.out.println("Updated ArrayList: " + animals); System.out.println("Removed Element: " + str); } }
输出
1 2 3 ArrayList: [Dog, Cat, Horse] Updated ArrayList: [Dog, Cat] Removed Element: Horse
在这里,remove()
方法将索引号 作为参数,删除索引编号下的元素.
ArrayList
中的常用方法
遍历ArrayList
可以使用for-each
遍历ArrayList
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Cow" ); languages.add("Cat" ); languages.add("Dog" ); System.out.println("ArrayList: " + languages); System.out.println("Accessing individual elements: " ); for (String language : languages) { System.out.print(language); System.out.print(", " ); } } }
输出:
1 2 3 ArrayList: [Cow, Cat, Dog] Accessing individual elements: Cow, Cat, Dog,
ArrayList
转成Array
我们可以使用toArray()
方法将ArrayList
转换为Array
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("C++" ); System.out.println("ArrayList: " + languages); String[] arr = new String[languages.size()]; languages.toArray(arr); System.out.print("Array: " ); for (String item : arr) { System.out.print(item + ", " ); } } }
输出:
1 2 ArrayList: [Java, Python, C++] Array: Java, Python, C++,
在上面的示例中,我们创建了一个名为language的数组列表。注意声明:
在这里,toArray()
方法将arraylist转换为数组并将其存储在arr中。
Array
转成ArrayList
我们还可以将Array
转换为arraylist
。为此,我们使用Arrays
类的asList()
方法。
要使用asList()
,我们必须首先导入java.util.Arrays
包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayList;import java.util.Arrays;class Main { public static void main (String[] args) { String[] arr = { "Java" , "Python" , "C++" }; System.out.print("Array: " ); for (String str : arr) { System.out.print(str); System.out.print(" " ); } ArrayList<String> languages = new ArrayList<>(Arrays.asList(arr)); System.out.println("\nArrayList: " + languages); } }
输出:
1 2 Array: Java Python C++ ArrayList: [Java, Python, C++]
注意:我们还可以使用Arrays.asList()
方法在一行中创建和初始化arraylist。例如,
1 ArrayList<String> animals = new ArrayList<>(Arrays.asList("Cat" , "Cow" , "Dog" ));
ArrayList
转成 String
我们可以使用ArrayList
类的toString()
方法将arraylist
转换为字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("Kotlin" ); System.out.println("ArrayList: " + languages); String str = languages.toString(); System.out.println("String: " + str); } }
输出:
1 2 ArrayList: [Java, Python, Kotlin] String: [Java, Python, Kotlin]
在这里,toString()
方法将整个arraylist
转换为单个字符串。
Vector
类是List
接口的一种实现,它使我们可以创建类似于ArrayList
类的可调整大小的数组。
Vector
vs.ArrayList
ArrayList
和Vector
均实现List
接口并提供相同的功能。但是,它们之间存在一些差异。
Vector
类同步每个单独的操作。这意味着每当我们要对向量执行某些操作时,Vector
类都会自动对该操作施加锁定。
这是因为当一个线程正在访问向量时,同时另一个线程试图访问它时,会生成一个称为ConcurrentModificationException
的异常。但是这样每次操作进行锁操作会降低整个的性能.
但是,在array list
中方法不同步。但可以使用Collections.synchronizedList()
方法将整个列表同步。
注意:建议使用ArrayList
代替Vector
,因为矢量不是线程安全的,并且效率较低。
创建 一个 Vector
1 Vector<Type> vector = new Vector<>();
此处,Type
表示链接列表的类型。
1 2 3 4 5 Vector<Integer> vector= new Vector<>(); Vector<String> vector= new Vector<>();
Vector
中的方法Vector
类还提供List接口的可调整大小的数组实现(类似于ArrayList
类)。一些Vector
方法是:
向Vector
中添加元素
add(element)
- 向Vector
中添加元素.
add(index,element)
- 向Vector
中指定位置添加元素.
addAll(vector)
- 将一个Vector
中所有元素添加另一个Vector
中.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.Vector;class Main { public static void main (String[] args) { Vector<String> mammals= new Vector<>(); mammals.add("Dog" ); mammals.add("Horse" ); mammals.add(2 , "Cat" ); System.out.println("Vector: " + mammals); Vector<String> animals = new Vector<>(); animals.add("Crocodile" ); animals.addAll(mammals); System.out.println("New Vector: " + animals); } }
输出:
1 2 Vector: [Dog, Horse, Cat] New Vector: [Crocodile, Dog, Horse, Cat]
获取Vector
中的元素
get(index)
- 返回指定下标下的元素
iterator()
- 返回一个迭代器对象以顺序访问vector
中元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.Iterator;import java.util.Vector;class Main { public static void main (String[] args) { Vector<String> animals= new Vector<>(); animals.add("Dog" ); animals.add("Horse" ); animals.add("Cat" ); String element = animals.get(2 ); System.out.println("Element at index 2: " + element); Iterator<String> iterate = animals.iterator(); System.out.print("Vector: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 Element at index 2 : Cat Vector: Dog, Horse, Cat,
移除Vector
中的元素
remove(index)
- 从指定位置删除元素.
removeAll()
- 移除所有的元素.
clear()
- 删除所有元素。它比removeAll()
性能更好.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.Vector;class Main { public static void main (String[] args) { Vector<String> animals= new Vector<>(); animals.add("Dog" ); animals.add("Horse" ); animals.add("Cat" ); System.out.println("Initial Vector: " + animals); String element = animals.remove(1 ); System.out.println("Removed Element: " + element); System.out.println("New Vector: " + animals); animals.clear(); System.out.println("Vector after clear(): " + animals); } }
输出:
1 2 3 4 Initial Vector: [Dog, Horse, Cat] Removed Element: Horse New Vector: [Dog, Cat] Vector after clear () : []
其它Vector
方法
Methods
Descriptions
set()
更改Vector
的元素
size()
返回Vector
中的大小
toArray()
将Vector
转换为数组
toString()
将Vector
转换为字符串
contains()
在Vector
中搜索指定的元素并返回布尔结果
Stack
类 Java集合框架具有一个名为Stack
的类,该类提供堆栈数据结构的功能。
Stack
类扩展了Vector
类。
Stack 实现 在Stack
中元素遵循Last In First Out
后进先出的原则.元素被添加到堆栈的顶部,并从堆栈的顶部移除。
创建一个 Stack
为了创建堆栈,我们必须首先导入java.util.Stack
包。导入包后,就可以使用Java
创建堆栈。
1 Stack<Type> stacks = new Stack<>();
在这里,Type
表示堆栈的类型
1 2 3 4 5 Stack<Integer> stacks = new Stack<>(); Stack<String> stacks = new Stack<>();
Stack 中的方法 由于Stack
扩展了Vector
类,因此它继承了Vector
的所有方法。
除了这些方法之外,Stack
类还包括5个与Vector
区别开来的方法。
push() 方法 要将元素添加到stack
的顶部,我们使用push()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Stack: " + animals); } }
输出:
1 Stack: [Dog, Horse, Cat]
pop() 方法 若要从堆栈顶部删除元素,我们使用 pop()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Initial Stack: " + animals); String element = animals.pop(); System.out.println("Removed Element: " + element); } }
输出:
1 2 Initial Stack: [Dog, Horse, Cat] Removed Element: Cat
peek() 方法 peek()
方法从堆栈顶部返回对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Stack: " + animals); String element = animals.peek(); System.out.println("Element at top: " + element); } }
输出:
1 2 Stack: [Dog, Horse, Cat] Element at top: Cat
search 方法 若要搜索堆栈中的元素,我们使用 search()
方法。它会返回元素所在下标.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Stack: " + animals); int position = animals.search("Horse" ); System.out.println("Position of Horse: " + position); } }
输出:
1 2 Stack: [Dog, Horse, Cat] Position of Horse: 2
empty()方法 为了检查堆栈是否为空,我们使用 empty()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Stack: " + animals); boolean result = animals.empty(); System.out.println("Is the stack empty? " + result); } }
输出:
1 2 Stack: [Dog, Horse, Cat] Is the stack empty? false
用 ArrayDeque
替代Stack
Stack
类提供了堆栈数据结构的直接实现。但是,建议不要使用它。而是使用ArrayDeque
类(实现Deque
接口).在Java中实现堆栈数据结构。
Queue 接口 Java collections
框架通过Queue
接口提供了队列数据结构的功能。它继承至Collection
.
实现Queue
的接口 为了使用Queue
的功能,我们需要使用实现它的类:
扩展Queue的接口 Queue
接口还通过各种子接口扩展:
Deque
BlockingQueue
BlockingDeque
Queue数据结构工作模式 在Queue
队列中,以(First In, First Out)
先进先出的方式存储和访问元素。
元素从后面添加,从前面删除。
怎么使用队列 在Java中,必须导入java.util.Queue
包才能使用Queue
。
1 2 3 4 5 6 7 8 9 Queue<String> animal1 = new LinkedList<>(); Queue<String> animal2 = new ArrayDeque<>(); Queue<String> animal 3 = new PriorityQueue<>();
在这里,我们分别创建了类LinkedList
,ArrayDeque
和PriorityQueue
的对象Animal1
,Animal2
和Animal3
。这些对象可以使用Queue接口的功能。
Queue中的方法 Queue
接口包括Collection
接口的所有方法。
Queue
接口的一些常用方法是:
add()
- 将指定的元素插入队列。如果任务成功,则add()
返回true,否则返回异常。
offer()
- 将指定的元素插入队列。如果任务成功,则offer()
返回true,否则返回false。
element()
- 返回队列的头元素。如果队列为空,则引发异常。
peek()
- 返回队列的头元素。如果队列为空,则返回null。
remove()
- 返回并删除队列的头元素。如果队列为空,则引发异常。
poll()
- 返回并删除队列的头元素.如果队列为空,则返回null。
实现Queue接口 LinkedList
类1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.Queue;import java.util.LinkedList;class Main { public static void main (String[] args) { Queue<Integer> numbers = new LinkedList<>(); numbers.offer(1 ); numbers.offer(2 ); numbers.offer(3 ); System.out.println("Queue: " + numbers); int accessedNumber = numbers.peek(); System.out.println("Accessed Element: " + accessedNumber); int removedNumber = numbers.poll(); System.out.println("Removed Element: " + removedNumber); System.out.println("Updated Queue: " + numbers); } }
输出:
1 2 3 4 Queue: [1 , 2 , 3 ] Accessed Element: 1 Removed Element: 1 Updated Queue: [2 , 3 ]
PriorityQueue
类1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.Queue;import java.util.PriorityQueue;class Main { public static void main (String[] args) { Queue<Integer> numbers = new PriorityQueue<>(); numbers.offer(5 ); numbers.offer(1 ); numbers.offer(2 ); System.out.println("Queue: " + numbers); int accessedNumber = numbers.peek(); System.out.println("Accessed Element: " + accessedNumber); int removedNumber = numbers.poll(); System.out.println("Removed Element: " + removedNumber); System.out.println("Updated Queue: " + numbers); } }
输出:
1 2 3 4 Queue: [1 , 5 , 2 ] Accessed Element: 1 Removed Element: 1 Updated Queue: [2 , 5 ]
PriorityQueue
类提供堆数据结构的功能。
与普通队列不同,优先级队列元素是按排序顺序检索的。
假设我们要按升序检索元素。在这种情况下,优先级队列的头部将是最小的元素。一旦检索到此元素,下一个最小的元素将是队列的开头。
重要的是要注意,优先级队列的元素可能未排序。但是,元素总是按排序顺序检索。
创建 PriorityQueue
为了创建优先级队列,我们必须导入java.util.PriorityQueue
包。导入程序包后,可以使用以下方法在Java中创建优先级队列。
1 PriorityQueue<Integer> numbers = new PriorityQueue<>();
在这里,我们创建了一个没有任何参数的优先级队列。在这种情况下,优先级队列的头部是队列的最小元素。并且元素以升序从队列中删除。
但是,我们可以借助Comparator
接口自定义元素的顺序。
PriorityQueue
中的方法PriorityQueue
类提供了Queue
接口中存在的所有方法的实现。
PriorityQueue
插入元素
add()
- 将指定的元素插入队列。如果队列已满,则将引发异常。
offer()
- 将指定的元素插入队列。如果队列已满,则返回false。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.PriorityQueue;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(); numbers.add(4 ); numbers.add(2 ); System.out.println("PriorityQueue: " + numbers); numbers.offer(1 ); System.out.println("Updated PriorityQueue: " + numbers); } }
输出:
1 2 PriorityQueue: [2 , 4 ] Updated PriorityQueue: [1 , 4 , 2 ]
在这里,我们创建了一个名为数字的优先级队列。我们已将4和2插入队列。
尽管在2之前插入了4,但队列的开头是2。这是因为优先级队列的头是队列中最小的元素。
然后,我们将1插入队列。现在重新排列了队列,以将最小的元素1存储到队列的开头。
PriorityQueue
获取元素要访问优先级队列中的元素,我们可以使用peek()
方法。此方法返回队列的头元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.PriorityQueue;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(); numbers.add(4 ); numbers.add(2 ); numbers.add(1 ); System.out.println("PriorityQueue: " + numbers); int number = numbers.peek(); System.out.println("Accessed Element: " + number); } }
输出:
1 2 PriorityQueue: [1 , 4 , 2 ] Accessed Element: 1
移除PriorityQueue
中的元素
romve()
- 从队列中删除指定的元素.
poll()
- 返回并删除队列的开头
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.PriorityQueue;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(); numbers.add(4 ); numbers.add(2 ); numbers.add(1 ); System.out.println("PriorityQueue: " + numbers); boolean result = numbers.remove(2 ); System.out.println("Is the element 2 removed? " + result); int number = numbers.poll(); System.out.println("Removed Element Using poll(): " + number); } }
输出:
1 2 3 PriorityQueue: [1 , 4 , 2 ] Is the element 2 removed? true Removed Element Using poll () : 1
遍历 PriorityQueue
要遍历优先级队列的元素,我们可以使用iterator()
方法。为了使用此方法,我们必须导入java.util.Iterator
包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.PriorityQueue;import java.util.Iterator;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(); numbers.add(4 ); numbers.add(2 ); numbers.add(1 ); System.out.print("PriorityQueue using iterator(): " ); Iterator<Integer> iterate = numbers.iterator(); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 PriorityQueue using iterator () : 1, 4, 2,
其它PriorityQueue
方法
Methods
Descriptions
contains(element)
在优先级队列中搜索指定的元素。如果找到该元素,则返回true,否则返回false。
size()
返回优先级队列的长度。
toArray()
将优先级队列转换为数组并返回它。
PriorityQueue Comparator Priority
元素以自然顺序(升序)检索。但是,我们可以自定义此排序。
为此,我们需要创建自己的比较器类来实现Comparator
接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.PriorityQueue;import java.util.Comparator;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(new CustomComparator()); numbers.add(4 ); numbers.add(2 ); numbers.add(1 ); numbers.add(3 ); System.out.print("PriorityQueue: " + numbers); } } class CustomComparator implements Comparator <Integer > { @Override public int compare (Integer number1, Integer number2) { int value = number1.compareTo(number2); if (value > 0 ) { return -1 ; } else if (value < 0 ) { return 1 ; } else { return 0 ; } } }
输出
1 PriorityQueue: [4 , 3 , 1 , 2 ]
在上面的示例中,我们创建了一个priorty
队列,将CustomComparator
类作为参数传递。
CustomComparator
类实现Comparator
接口。
然后,我们重写compare()
方法。现在,该方法使元素的头元素为最大数。
Java collections
框架Deque
提供了双端队列功能.它继承至Queue
接口.
Deque
工作模式
在常规队列中,元素是从后面添加的,而从前面删除的。但是,在双端队列中,我们可以从前面和后面插入和删除元素(insert and remove elements from both front and rear
)
Deque
接口的实现为了使用Deque
接口的功能,我们需要使用实现该接口的类:
怎么使用 Deque
在Java中,我们必须导入java.util.Deque
包才能使用Deque
。
1 2 3 4 5 Deque<String> animal1 = new ArrayDeque<>(); Deque<String> animal2 = new LinkedList<>();
在这里,我们分别创建了类ArrayDeque
和LinkedList
的对象animal1
和animal2
。
Deque
中的方法Deque
继承至Queue
接口,它继承了所有Queue
接口.
除Queue
接口中可用的方法外,Deque
接口还包括以下方法:
addFirst()
- 在双端队列的开头添加指定的元素。如果双端队列已满,则引发异常。
addLast()
- 在双端队列的末尾添加指定的元素。如果双端队列已满,则引发异常.
offerFirst()
- 在双端队列的开头添加指定的元素。如果双端队列已满,则返回false。
offerLast()
- 在双端队列的末尾添加指定的元素。如果双端队列已满,则返回false。
getFirst()
- 返回双端队列的第一个元素。如果双端队列为空,则引发异常。
getLast()
- 返回双端队列的最后一个元素。如果双端队列为空,则引发异常。
peekFirst()
- 返回双端队列的第一个元素。如果双端队列为空,则返回null。
peekLast()
- 返回双端队列的最后一个元素。如果双端队列为空,则返回null。
removeFirst()
- 返回并删除双端队列的第一个元素。如果双端队列为空,则引发异常。
removeLast()
- 返回并删除双端队列的最后一个元素。如果双端队列为空,则引发异常。
pollFirst()
- 返回并删除双端队列的第一个元素。如果双端队列为空,则返回null。
pollLast()
- 返回并删除双端队列的最后一个元素。如果双端队列为空,则返回null。
Deque 作为堆栈数据结构 Java Collections框架的Stack类提供了堆栈的实现。
但是,建议将Deque
用作堆栈而不是Stack
类。这是因为Stack的方法是同步的。
以下是Deque接口提供的用于实现堆栈的方法:
push()
- 在双端队列的开头添加一个元素
pop()
- 从双端队列的开头删除元素
peek()
- 从双端队列的开头返回一个元素
实现Deque
了类ArrayDeque
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.Deque;import java.util.ArrayDeque;class Main { public static void main (String[] args) { Deque<Integer> numbers = new ArrayDeque<>(); numbers.offer(1 ); numbers.offerLast(2 ); numbers.offerFirst(3 ); System.out.println("Deque: " + numbers); int firstElement = numbers.peekFirst(); System.out.println("First Element: " + firstElement); int lastElement = numbers.peekLast(); System.out.println("Last Element: " + lastElement); int removedNumber1 = numbers.pollFirst(); System.out.println("Removed First Element: " + removedNumber1); int removedNumber2 = numbers.pollLast(); System.out.println("Removed Last Element: " + removedNumber2); System.out.println("Updated Deque: " + numbers); } }
输出:
1 2 3 4 5 6 Deque: [3 , 1 , 2 ] First Element: 3 Last Element: 2 Removed First Element: 3 Removed Last Element: 2 Updated Deque: [1 ]
Javacollections
框架的LinkedList
类提供了链表数据结构(双重链表)的功能。
链表中的每个元素都称为节点。它包含3个字段:
Prev
- 将前一个元素的地址存储在列表中。第一个元素为null
Next
- 在列表中存储下一个元素的地址。最后一个元素为null
Data
- 存储实际数据.
创建 Java LinkedList 这是我们如何在Java中创建链接列表的方法:
1 LinkedList<Type> linkedList = new LinkedList<>();
此处,Type
表示链接列表的类型。
1 2 3 4 5 LinkedList<Integer> linkedList = new LinkedList<>(); LinkedList<String> linkedList = new LinkedList<>();
例子🌰 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> animals = new LinkedList<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Cow" ); System.out.println("LinkedList: " + animals); } }
输出
1 LinkedList: [Dog, Cat, Cow]
在上面的示例中,我们创建了一个名为Animals
的LinkedList
。
在这里,我们使用add()
方法将元素添加到LinkedList
。
LinkedList 中的工作模式 链接列表中的元素未按顺序存储。相反,它们分散并通过链接(上一个和下一个)连接。
在这里,链接列表中包含3个元素。
Dog
- 它是第一个保留null
为上一个地址,而Cat
的地址为下一个地址的元素
Cat
- 它是第二个元素,将Dog
的地址作为前一个地址,将Cow
的地址作为下一个地址
Cow
-它是将Cat
的地址保留为前一个地址而将null
保留为下一个元素的最后一个元素
LinkedList
中的方法LinkedList
提供了多种方法,使我们可以在链表中执行不同的操作。
向 LinkedList
中添加元素 我们可以使用add()
方法在LinkedList的末尾添加一个元素(节点)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> animals = new LinkedList<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Cow" ); System.out.println("LinkedList: " + animals); animals.add(1 , "Horse" ); System.out.println("Updated LinkedList: " + animals); } }
输出:
1 2 LinkedList: [Dog, Cat, Cow] Updated LinkedList: [Dog, Horse, Cat, Cow]
在上面的示例中,我们创建了一个名为Animals
的LinkedList
。在这里,我们使用add()
方法向动物添加元素。
注意:
1 animals.add(1 , "Horse" );
在这里,我们使用了索引号参数,它是一个可选参数,用于指定添加新元素的位置。
获取 LinkedList元素 LinkedList类的get()
方法用于访问LinkedList中的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> languages = new LinkedList<>(); languages.add("Python" ); languages.add("Java" ); languages.add("JavaScript" ); System.out.println("LinkedList: " + languages); String str = languages.get(1 ); System.out.print("Element at index 1: " + str); } }
输出
1 2 LinkedList: [Python, Java, JavaScript] Element at index 1 : Java
在上面的示例中,我们将get()
方法的参数1
一起使用。在这里,该方法返回索引为1
的元素。
我们还可以使用iterator()
和listIterator()
方法访问LinkedList的元素。
修改LinkedList
中的元素 LinkedList
类的set()
方法用于更改LinkedList的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> languages = new LinkedList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("JavaScript" ); languages.add("Java" ); System.out.println("LinkedList: " + languages); languages.set(3 , "Kotlin" ); System.out.println("Updated LinkedList: " + languages); } }
输出:
1 2 LinkedList: [Java, Python, JavaScript, Java] Updated LinkedList: [Java, Python, JavaScript, Kotlin]
1 languages.set(3 , "Kotlin" );
在这里,set()
方法将索引3
处的元素更改为Kotlin
。
移除LinkedList中的元素 LinkedList
类的remove()
方法用于从LinkedList
中删除元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> languages = new LinkedList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("JavaScript" ); languages.add("Kotlin" ); System.out.println("LinkedList: " + languages); String str = languages.remove(1 ); System.out.println("Removed Element: " + str); System.out.println("Updated LinkedList: " + languages); } }
输出:
1 2 3 LinkedList: [Java, Python, JavaScript, Kotlin] Removed Element: Python New LinkedList: [Java, JavaScript, Kotlin]
在这里,remove()
方法将索引号作为参数。并且删除索引编号指定的元素。
其它常用方法
Methods
Description
contains()
检查LinkedList是否包含元素
indexOf()
返回元素第一次出现的索引
lastIndexOf()
返回元素最后一次出现的索引
clear()
删除LinkedList的所有元素
iterator()
返回用于迭代LinkedList的迭代器
LinkedList 作为 Deque 和Queue 由于LinkedList
类还实现了Queue
和Deque
接口,它也可以实现这些接口的方法。
以下是一些常用方法:
Methods
Descriptions
addFirst()
将指定的元素添加到链接列表的开头
addLast()
将指定的元素添加到链接列表的末尾
getFirst()
返回第一个元素
getLast()
返回最后一个元素
removeFirst()
删除第一个元素
removeLast()
删除最后一个元素
peek()
返回链表的第一个元素(头)
poll()
返回并从链接列表中删除第一个元素
offer()
将指定的元素添加到链接列表的末尾
LinkedList 作为 Queue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.LinkedList;import java.util.Queue;class Main { public static void main (String[] args) { Queue<String> languages = new LinkedList<>(); languages.add("Python" ); languages.add("Java" ); languages.add("C" ); System.out.println("LinkedList: " + languages); String str1 = languages.peek(); System.out.println("Accessed Element: " + str1); String str2 = languages.poll(); System.out.println("Removed Element: " + str2); System.out.println("LinkedList after poll(): " + languages); languages.offer("Swift" ); System.out.println("LinkedList after offer(): " + languages); } }
输出:
1 2 3 4 5 LinkedList: [Python, Java, C] Accessed Element: Python Removed Element: Python LinkedList after poll () : [Java, C] LinkedList after offer () : [Java, C, Swift]
LinkedList as Deque 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.LinkedList;import java.util.Deque;class Main { public static void main (String[] args) { Deque<String> animals = new LinkedList<>(); animals.add("Cow" ); System.out.println("LinkedList: " + animals); animals.addFirst("Dog" ); System.out.println("LinkedList after addFirst(): " + animals); animals.addLast("Zebra" ); System.out.println("LinkedList after addLast(): " + animals); animals.removeFirst(); System.out.println("LinkedList after removeFirst(): " + animals); animals.removeLast(); System.out.println("LinkedList after removeLast(): " + animals); } }
输出:
1 2 3 4 5 LinkedList: [Cow] LinkedList after addFirst () : [Dog, Cow] LinkedList after addLast () : [Dog, Cow, Zebra] LinkedList after removeFirst () : [Cow, Zebra] LinkedList after removeLast () : [Cow]
遍历 LinkedList 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> animals = new LinkedList<>(); animals.add("Cow" ); animals.add("Cat" ); animals.add("Dog" ); System.out.println("LinkedList: " + animals); System.out.println("Accessing linked list elements:" ); for (String animal: animals) { System.out.print(animal); System.out.print(", " ); } } }
输出:
1 2 3 LinkedList: [Cow, Cat, Dog] Accessing linked list elements: Cow, Cat, Dog,
LinkedList Vs. ArrayList Java ArrayList
和LinkedList
都实现Collections
框架的List
接口。但是,它们之间存在一些差异。
LinkedList
ArrayList
实现List
,Queue
和Deque
接口。
实现List
接口
一个单位会存三个值
一个单位存一个值
提供双向链表实现
提供可调整大小的数组实现
每当添加元素时,上一个和下一个地址都会更改
每当添加元素时,该位置之后的所有元素都会移动
要访问元素,我们需要从头开始迭代到元素
可以使用索引随机访问元素
在Java中我们可以通过接口创建LinkedList
1 2 3 4 5 6 7 8 List<String> animals1 = new LinkedList<>(); Queue<String> animals2 = new LinkedList<>(); Deque<String> animals3 = new LinkedList<>();
在这里,如果LinkedList是使用一个接口创建的,则我们不能使用其他接口提供的方法。也就是说,animals1
不能使用特定于Queue
和Deque
接口的方法。
在Java中,我们可以使用ArrayDeque类使用数组来实现队列和双端队列数据结构。
ArrayDeque
实现了Queue
和Deque
接口
创建 ArrayDeque 为了创建数组双端队列,我们必须导入java.util.ArrayDeque
包。
1 ArrayDeque<Type> animal = new ArrayDeque<>();
在此,Type
表示数组双端队列的类型。
1 2 3 4 5 ArrayDeque<String> animals = new ArrayDeque<>(); ArrayDeque<Integer> age = new ArrayDeque<>();
ArrayDeque 中的方法 ArrayDeque
类为Queue
和Deque
接口中存在的所有方法提供实现。
Deque插入元素 添加元素通过 add()
、addFirst()
、addLast()
add()
- 在数组双端队列的末尾插入指定的元素
addFirst()
- 在数组双端队列的开始处插入指定的元素
addLast()
- 在数组双端队列的末尾插入指定的
注意: 如果数组双端队列已满,则所有这些方法add(),addFirst()和addLast()都会引发IllegalStateException。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.addFirst("Cat" ); animals.addLast("Horse" ); System.out.println("ArrayDeque: " + animals); } }
输出:
1 ArrayDeque: [Cat, Dog, Horse]
插入数据offer()
、offerFirst()
、offerLast()
offer()
- 在数组双端队列的末尾插入指定的元素
offerFirst()
- 在数组双端队列的开始处插入指定的元素
offerLast()
- 在数组双端队列的末尾插入指定的元素
注意: 如果成功插入元素,则offer(),offerFirst()和offerLast()返回true;否则,返回true。如果数组双端队列已满,则这些方法将返回false。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.offer("Dog" ); animals.offerFirst("Cat" ); animals.offerLast("Horse" ); System.out.println("ArrayDeque: " + animals); } }
输出:
1 ArrayDeque: [Cat, Dog, Horse]
注意: 如果阵列双端队列已满
add()方法将引发异常
offer()方法返回false
获取ArrayDeque元素 获取元素getFirst()
和getLast()
getFirst()
- 返回数组双端队列的第一个元素
getLast()
- 返回数组双端队列的最后一个元素
注意: 如果数组双端队列为空,则getFirst()
和getLast()
引发NoSuchElementException
。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); String firstElement = animals.getFirst(); System.out.println("First Element: " + firstElement); String lastElement = animals.getLast(); System.out.println("Last Element: " + lastElement); } }
输出:
1 2 3 ArrayDeque: [Dog, Cat, Horse] First Element: Dog Last Element: Horse
使用peek()
,peekFirst()
和peekLast()
方法获取元素
peek()
- 返回数组双端队列的第一个元素
peekFirst()
- 返回数组双端队列的第一个元素(与peek()
等效)
peekLast()
-返回数组双端队列的最后一个元素
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); String element = animals.peek(); System.out.println("Head Element: " + element); String firstElement = animals.peekFirst(); System.out.println("First Element: " + firstElement); String lastElement = animals.peekLast(); System.out.println("Last Element: " + lastElement); } }
输出:
1 2 3 4 ArrayDeque: [Dog, Cat, Horse] Head Element: Dog First Element: Dog Last Element: Horse
注意: 如果数组双端队列为空,则peek()
,peekFirst()
和getLast()
会引发NoSuchElementException
。
移除ArrayDeque
中的元素 移除元素remove()
、removeFirst()
、removeLast()
remove()
- 返回并从数组双端队列的第一个元素中删除一个元素.
removeFirst()
- 返回并从数组双端队列中删除第一个元素(与remove()
等效)
remove(element)
- 返回并从数组双端队列的头部移除指定的元素
removeLast()
- 返回并从数组双端队列中删除最后一个元素
注意: 如果数组双端队列为空,则remove()
,removeFirst()
和removeLast()
方法将引发异常。另外,如果未找到元素,则remove(element)
会引发异常。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Cow" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); String element = animals.remove(); System.out.println("Removed Element: " + element); System.out.println("New ArrayDeque: " + animals); String firstElement = animals.removeFirst(); System.out.println("Removed First Element: " + firstElement); String lastElement = animals.removeLast(); System.out.println("Removed Last Element: " + lastElement); } }
输出:
1 2 3 4 5 ArrayDeque: [Dog, Cat, Cow, Horse] Removed Element: Dog New ArrayDeque: [Cat, Cow, Horse] Removed First Element: Cat Removed Last Element: Horse
移除元素poll()
、pollFirst()
、pollLast()
方法
poll()
- 返回并删除数组双端队列的第一个元素
pollFirst()
- 返回并删除数组双端队列的第一个元素(与poll()
等效)
pollLast()
- 返回并删除数组双端队列的最后一个元素
注意: 如果数组双端队列为空,则如果找不到该元素,则poll()
,pollFirst()
和pollLast()
返回nul
l。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Cow" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); String element = animals.poll(); System.out.println("Removed Element: " + element); System.out.println("New ArrayDeque: " + animals); String firstElement = animals.pollFirst(); System.out.println("Removed First Element: " + firstElement); String lastElement = animals.pollLast(); System.out.println("Removed Last Element: " + lastElement); } }
输出:
1 2 3 4 5 ArrayDeque: [Dog, Cat, Cow, Horse] Removed Element: Dog New ArrayDeque: [Cat, Cow, Horse] Removed First Element: Cat Removed Last Element: Horse
移除所有元素clear()
要从数组双端队列中删除所有元素,我们使用clear()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); animals.clear(); System.out.println("New ArrayDeque: " + animals); } }
输出:
1 2 ArrayDeque: [Dog, Cat, Horse] New ArrayDeque: []
遍历 ArrayDeque
iterator()
- 返回一个迭代器,该迭代器可用于遍历数组双端队列
descendingIterator()
- 返回一个迭代器,该迭代器可用于以相反顺序遍历数组双端队列
为了使用这些方法,我们必须导入java.util.Iterator
包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.ArrayDeque;import java.util.Iterator;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.print("ArrayDeque: " ); Iterator<String> iterate = animals.iterator(); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } System.out.print("\nArrayDeque in reverse order: " ); Iterator<String> desIterate = animals.descendingIterator(); while (desIterate.hasNext()) { System.out.print(desIterate.next()); System.out.print(", " ); } } }
输出:
1 2 ArrayDeque: [Dog, Cat, Horse] ArrayDeque in reverse order: [Horse, Cat, Dog]
其他方法
Methods
Descriptions
element()
从数组双端队列的头部返回一个元素。
contains(element)
在数组双端队列中搜索指定的元素。如果找到该元素,则返回true,否则返回false。
size()
返回数组双端队列的长度。
toArray()
将数组双端队列转换为数组并返回。
clone()
创建数组双端队列的副本并返回它。
ArrayDeque作为栈(Stack) 要在Java中实现LIFO(后进先出)堆栈,建议使用deque
。ArrayDeque
会比Stack
更快些.
ArrayDeque
提供了以下可用于实现stack
的方法。
push
- 添加一个元素到stack
顶部
peek
-返回stack
顶部的元素
pop()
- 移除并返回stack
顶部的元素
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> stack = new ArrayDeque<>(); stack.push("Dog" ); stack.push("Cat" ); stack.push("Horse" ); System.out.println("Stack: " + stack); String element = stack.peek(); System.out.println("Accessed Element: " + element); String remElement = stack.pop(); System.out.println("Removed element: " + remElement); } }
输出:
1 2 3 Stack: [Horse, Cat, Dog] Accessed Element: Horse Removed Element: Horse
ArrayDeque
VsLinkedList Class
ArrayDeque
和Java LinkedList
均实现Deque
接口。但是他们存在一些差别
LinkedList
支持null
元素,但是ArrayDeque
不支持
链表中的每个节点都包含指向其他节点的链接。这就是为什么LinkedList
比ArrayDeque
需要更多存储的原因。
如果要实现队列或双端队列数据结构,ArrayDeque
可能比LinkedList
更快。
BlockingQueue
接口扩展了Queue
接口.它允许任何操作等待成功执行。
例如,如果我们要从空队列中删除元素,则blcoking queue
允许删除操作等待,直到队列中包含一些要删除的元素。
实现BlockingQueue
由于BlockingQueue
是一个接口,因此我们无法提供它的直接实现。为了使用BlockingQueue
的功能,我们需要使用实现它的类。
如何使用blocking queues
为了使用BlockingQueue
,我们必须导入java.util.concurrent.BlockingQueue
包。
1 2 3 4 5 BlockingQueue<String> animal1 = new ArraryBlockingQueue<>(); BlockingQueue<String> animal2 = new LinkedBlockingQueue<>();
在这里,我们分别创建了类ArrayBlockingQueue
和LinkedBlockingQueue
的对象animal1
和animal2
。这些对象可以使用BlockingQueue
接口的功能。
BlockingQueue方法 根据队列是满还是空,阻塞队列的方法可以分为3类:
这些方法会抛出异常
add()
- 将元素插入到队列末尾的blocking queue
队列中。如果队列以满,则抛出异常
element()
- 返回blocking queue
头部元素.如果队列为空则抛出异常
remove()
- 从blocking queue
移除元素.如果队列为空则抛出异常.
返回一些值的方法
offer()
- 将元素插入到blocking queue
队列的尾部.如果队列已满,则返回false
.
peek()
- 返回blocking queue
队列头部元素.如果队列为空则返回null
.
poll()
- 从blocking queue
队列删除一个元素. 如果队列为空,则返回null
.
offer()
和poll()
更多信息offer()
和poll()
方法可以设定时间。也就是说,我们可以传递时间单位作为参数。例如:
1 offer(value, 100 , milliseconds)
value
- 需要插入到队列的数据
100
-延迟时间
milliseconds
- 时间单位
这意味着offer()
方法将尝试将元素插入block queue
用100毫秒。如果无法在100毫秒内插入元素,则该方法返回false
。
注意: 除了milliseconds
我们还可以配置:days
,hours
,minutes
,seconds
,microseconds
,nanoseconds
用于offer()
和poll()
方法.
blocks中的操作符 BlockingQueue
提供了等待操作队列方法,如果队列为空或者已满.
put()
- 将元素插入到blocking queue
。如果队列已满,它将等待直到队列有空间插入元素。
take()
- 从blocking queue
移除第一个元素并返回一个元素.如果队列为空,则等待队列有元素再删除.
假设我们想将元素插入队列。如果队列已满,则put()
方法将等待,直到队列有空间插入元素。
同样,如果我们要从队列中删除元素。如果队列为空,则take()方法将等待直到队列包含要删除的元素。
ArrayBlockingQueue
实现BlockingQueue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.concurrent.BlockingQueue;import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { BlockingQueue<Integer> numbers = new ArrayBlockingQueue<>(5 ); try { numbers.put(2 ); numbers.put(1 ); numbers.put(3 ); System.out.println("BLockingQueue: " + numbers); int removedNumber = numbers.take(); System.out.println("Removed Number: " + removedNumber); } catch (Exception e) { e.getStackTrace(); } } }
输出:
1 2 BlockingQueue: [2 , 1 , 3 ] Removed Element: 2
为什么使用BlockingQueue
在Java中,BlockingQueue
被视为线程安全的集合。这是因为它在多线程操作中可能会有所帮助。
假设一个线程正在将元素插入队列,而另一个线程正在从队列中删除元素。
现在,如果第一个线程运行较慢,则阻塞队列可使第二个线程等待,直到第一个线程完成其操作。
ArrayBlockingQueue
实现了Java Collections
框架中blocking queue
接口通过数组.
创建ArrayBlockingQueue
创建一个数组blocking queue
,我们必须导入java.util.concurrent.ArrayBlockingQueue
包.
导入包后,可以使用以下方法在Java
中创建数组blocking queue
:
1 ArrayBlockingQueue<Type> animal = new ArrayBlockingQueue<>(int capacity);
Type
- array blocking queue的类型
capacity
- 这个 array blocking queue大小
1 2 3 4 5 ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); ArrayBlockingQueue<Integer> age = new ArrayBlockingQueue<>(5 );
注意: 必须提供数组的大小.
ArrayBlockingQueue
中方法ArrayBlockingQueue
类提供BlockingQueue
接口中所有方法的实现。
这些方法用于从数组blocking queue
中插入,访问和删除元素。
put()
和take()
方法支持blocking
操作在array blocking queue
.
这个两个方法会和array blocking queue
其他类型队列有区别.
插入元素
add()
- 将指定的元素插入到array blocking queue
.如果队列满了则抛出异常.
offer()
- 将指定的元素插入到array blocking queue
.如果队列满了则返回false
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.offer("Horse" ); System.out.println("ArrayBlockingQueue: " + animals); } }
输出:
1 ArrayBlockingQueue: [Dog, Cat, Horse]
获取元素
peek()
- 从array blocking queue
头部返回一个元素.如果队列是空则返回null
iterator()
- 返回一个迭代器对象,以顺序访问array blocking queue
中的元素。如果队列为空,则抛出异常。我们必须导入java.util.Iterator
包才能使用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.concurrent.ArrayBlockingQueue;import java.util.Iterator;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayBlockingQueue: " + animals); String element = animals.peek(); System.out.println("Accessed Element: " + element); Iterator<String> iterate = animals.iterator(); System.out.print("ArrayBlockingQueue Elements: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 3 ArrayBlockingQueue: [Dog, Cat, Horse] Accessed Element: Dog ArrayBlockingQueue Elements: Dog, Cat, Horse,
移除元素
remove()
- 移除并返回删除的制定元素从array blocking queue
.如果队列为空则抛出异常.
poll()
- 移除并返回删除的制定元素从array blocking queue
.如果队列为空则返回null
clear()
- 从array block queue
所有元素.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayBlockingQueue: " + animals); String element1 = animals.remove(); System.out.println("Removed Element:" ); System.out.println("Using remove(): " + element1); String element2 = animals.poll(); System.out.println("Using poll(): " + element2); animals.clear(); System.out.println("Updated ArrayBlockingQueue: " + animals); } }
输入:
1 2 3 4 5 ArrayBlockingQueue: [Dog, Cat, Horse] Removed Elements: Using remove () : Dog Using poll () : Cat Updated ArrayBlockingQueue: []
put()
和take()
方法在多线程处理中,我们可以使用put()
和take()
阻止一个线程的操作,以使其与另一个线程同步。这些方法将等待,直到可以成功执行。
put()
方法将元素添加到array blocking queue
尾部.
如果array blocking queue
已满,它将等待,直到array blocking queue
中有空间可添加元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); try { animals.put("Dog" ); animals.put("Cat" ); System.out.println("ArrayBlockingQueue: " + animals); } catch (Exception e) { System.out.println(e); } } }
输出:
1 ArrayBlockingQueue: [Dog, Cat]
在这里,如果put()
方法在等待时被中断,则可能会抛出InterruptedException
。因此,我们必须将其包含在try..catch
块中。
take()
方法删除array blocking queue
中头部元素,并返回.
如果array blocking queue
为空, 则等到array blocking queue
有元素可以删除.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); try { animals.put("Dog" ); animals.put("Cat" ); System.out.println("ArrayBlockingQueue: " + animals); String element = animals.take(); System.out.println("Removed Element: " + element); } catch (Exception e) { System.out.println(e); } } }
输出:
1 2 ArrayBlockingQueue: [Dog, Cat] Removed Element: Dog
在这里,如果take()
方法在等待时被中断,则会抛出InterrupedException
。因此,我们必须将其封闭在try ... catch
块中。
其它方法
Methods
Descriptions
contains(element)
在array blocking queue
搜索指定的元素.如果找到元素就返回true
,没有找到则返回false
.
size()
返回数组的长度
toArray()
转换array blocking queue
为数组
toString()
转换array blocking queue
为字符串
为啥使用ArrayBlockingQueue
ArrayBlockingQueue
使用数组作为其内部存储。
它被认为是线程安全的集合。因此,它通常用于多线程应用程序中。
假设一个线程正在将元素插入队列,而另一个线程正在从队列中删除元素。
现在,如果第一个线程比第二个线程慢,那么数组阻塞队列可以使第二个线程等待,直到第一个线程完成其操作。
Java Collections
框架中的LinkedBlockingQueue
实现了阻塞队列,实现了linked list
接口.
创建LinkedBlockingQueue
为了创建linked blocking queue
我们必须导入java.util.concurrent.LinkedBlockingQueue
包.
不指定大小 1 LinkedBlockingQueue<Type> animal = new LinkedBlockingQueue<>();
此处的默认初始容量为231-1。
指定大小 1 LinkedBlockingQueue<Type> animal = new LinkedBlockingQueue<>(int capacity);
Type
- linked blocking queue
的类型
capacity
- linked blocking queue
的大小
1 2 3 4 5 LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); LinkedBlockingQueue<Integer> age = new LinkedBlockingQueue<>(5 );
注意:不必提供链接列表的大小。
LinkedBlockingQueue中的方法 LinkedBlockingQueue
类提供BlockingQueue
接口中所有方法的实现。
这些方法提供了LinkedBlockingQueue
中插入,获取,删除元素的方法.
另外,我们还将学习支持LinkedBlockingQueue
中的阻塞操作的两种方法put()
和take()
。
这两种方法将LinkedBlockingQueue
与其他典型队列区分开来。
插入元素
add()
- 将指定的元素插入到LinkedBlockingQueue
中. 如果队列满了则它会抛出异常.
offer()
- 将指定的元素插入到LinkedBlockingQueue
中.如果队列满了则它会返回false
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.concurrent.LinkedBlockingQueue;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.offer("Horse" ); System.out.println("LinkedBlockingQueue: " + animals); } }
输出:
1 LinkedBlockingQueue: [Dog, Cat, Horse]
获取元素
peek()
- 将LinkedBlockingQueue
中的第一个元素返回.如果队列为空,则返回null
iterator
- 返回LinkedBlockQueue
元素的迭代器.如果队列为空则它会抛出一个错误.使用它我们需要引入java.util.Iterator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.concurrent.LinkedBlockingQueue;import java.util.Iterator;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("LinkedBlockingQueue: " + animals); String element = animals.peek(); System.out.println("Accessed Element: " + element); Iterator<String> iterate = animals.iterator(); System.out.print("LinkedBlockingQueue Elements: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 3 LinkedBlockingQueue: [Dog, Cat, Horse] Accessed Element: Dog LinkedBlockingQueue Elements: Dog, Cat, Horse,
移除元素
remove()
- 返回并LinkedBlockingQueue
中删除指定的元素。当前队列如果为空则抛出异常.
poll()
- 删除并返回LinkedBlockQueue
的元素.如果队列为空则返回null
.
clear()
- 移除LinkedBlockQueue
中的所有元素.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.concurrent.LinkedBlockingQueue;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("LinkedBlockingQueue " + animals); String element1 = animals.remove(); System.out.println("Removed Element:" ); System.out.println("Using remove(): " + element1); String element2 = animals.poll(); System.out.println("Using poll(): " + element2); animals.clear(); System.out.println("Updated LinkedBlockingQueue " + animals); } }
输出:
1 2 3 4 5 LinkedBlockingQueue: [Dog, Cat, Horse] Removed Elements: Using remove () : Dog Using poll () : Cat Updated LinkedBlockingQueue: []
put()
和take()
方法在多线程处理中,我们可以使用put()
和take()
阻止一个线程的操作,以使其与另一个线程同步。这些方法将等待,直到可以成功执行。
put()
方法要将指定的元素插入到LinkedBlockingQueue
的末尾,我们使用put()
方法。
如果链接的队列已满,它将等待,直到链接的队列中有足够的空间来插入元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.concurrent.LinkedBlockingQueue;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); try { animals.put("Dog" ); animals.put("Cat" ); System.out.println("LinkedBlockingQueue: " + animals); } catch (Exception e) { System.out.println(e); } } }
输出:
1 LinkedBlockingQueue: [Dog, Cat]
在这里,如果put()
方法在等待时被中断,则可能会抛出InterruptedException
。
take()
方法移除并返回LinkedBlockingQueue
头部元素.
如果LinkedBlockingQueue
为空,它会等待LinkedBlockingQueue
存在元素并将它删除.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.concurrent.LinkedBlockingQueue;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); try { animals.put("Dog" ); animals.put("Cat" ); System.out.println("LinkedBlockingQueue: " + animals); String element = animals.take(); System.out.println("Removed Element: " + element); System.out.println("New LinkedBlockingQueue: " + animals); } catch (Exception e) { System.out.println(e); } } }
输出:
1 2 3 LinkedBlockingQueue: [Dog, Cat] Removed Element: Dog New LinkedBlockingQueue: [Cat]
在这里,如果take()
方法在等待时被中断,则会抛出InterrupedException
。因此,我们必须将其封闭在try ... catch
块中。
其它方法
Methods
Descriptions
contains(element)
在LinkedBlockingQueue
搜索是否存在指定元素 . 如果找到则返回true
,否则返回false
.
size()
返回LinkedBlockingQueue
的大小
toArray()
将LinkedBlockingQueue
转换成数组
toString()
将LinkedBlockingQueue
转换成字符串
为什么使用LinkedBlockingQueue
LinkedBlockingQueue
使用链接列表作为其内部存储。
它被认为是线程安全的集合。因此,它通常用于多线程应用程序中。
假设一个线程正在将元素插入队列,而另一个线程正在从队列中删除元素。
现在,如果第一个线程比第二个线程慢,然后LinkedBlockingQueue
可以使第二个线程等待,直到第一个线程完成其操作。
##Map 接口
Java collections framework
的Map
接口提供了map
数据结构的功能。
Working of Map Java中,元素在Map
中以key/value
形式保存着。Keys
是与Values
关联的唯一值。
一个map
中不会包含重复的keys
,每一个key
都有关联的唯一一个value
我们可以使用与它们关联的键来访问和修改值。
在上图中,key/value
有:us/United States
、br/Brazil
、es/Spain
.
我们可以使用它们的对应键访问这些值。
注意: Map界面维护3个不同的集合:
keys
集合
values
集合
key/value
关联值集合
我们可以分别访问:keys
、values
、key/value
实现Map
由于Map
是interface
,因此我们无法从中创建对象。
为了使用Map接口的功能,我们可以使用以下类:
这些类在集合框架中定义并实现Map接口。
扩展 Map 接口 这些子接口还扩展了Map接口:
怎样使用 Map
在Java中,必须导入java.util.Map
包才能使用Map
。
1 2 Map<Key, Value> numbers = new HashMap<>();
在上面的代码中,我们创建了一个名为numbers
的Map
。我们已经使用HashMap
类来实现Map
接口。
Key
- 用于关联map
中每个元素(值)的唯一标识符.
Value
- map
中key
关联的元素
Map 中常用方法 Map
接口包含Collection
接口的所有方法。这是因为Collection
是Map
的超级接口。
除了Collection
中可用的方法外,Map
还包括以下方法:
put(K, V)
- 将key-K
和value-V
插入到map
中,如果key
已经存在,则V
替换旧值
putAll()
- 将指定map
中所有内容插入到当前map
中
putIfAbsent(K, V)
- 如果K
与V
并没有关联,则将它们插入到map
中
get(K)
- 返回与指定keyK
关联的值。如果找不到该K
,则返回null
getOrDefault(K, defaultValue)
- 返回与指定keyK
关联的值,如果key不存在,则返回defaultValue
containsKey(K)
- 检查map
中是否存在指定的keyK
containsValue(V)
- 检查map
中是否存在指定的valueV
replace(K,V)
- 用新的valueV
替换,keyK
中旧的value
replace(K, oldValue, newValue)
- 仅当keyK
与valueoldValue
关联时,才用新valuenewValue
替换keyK
的值
remove(K)
- 从map
中删除key是K
中的数据
remove(K, V)
- 从map
中删除key是K
,value是V
的数据
keySet()
- 返回map
中所有key的集合
values()
- 返回map
中所有value的集合
entrySet()
- 返回map
中key/value
集合
实现Map接口 HashMap 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.Map;import java.util.HashMap;class Main { public static void main (String[] args) { Map<String, Integer> numbers = new HashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); System.out.println("Map: " + numbers); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); System.out.println("Entries: " + numbers.entrySet()); int value = numbers.remove("Two" ); System.out.println("Removed Value: " + value); } }
输出:
1 2 3 4 5 Map: {One=1 , Two=2 } Keys: [One, Two] Values: [1 , 2 ] Entries: [One=1 , Two=2 ] Removed Value: 2
TreeMap 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.Map;import java.util.TreeMap;class Main { public static void main (String[] args) { Map<String, Integer> values = new TreeMap<>(); values.put("Second" , 2 ); values.put("First" , 1 ); System.out.println("Map using TreeMap: " + values); values.replace("First" , 11 ); values.replace("Second" , 22 ); System.out.println("New Map: " + values); int removedValue = values.remove("First" ); System.out.println("Removed Value: " + removedValue); } }
输出:
1 2 3 Map using TreeMap: {First=1 , Second=2 } New Map: {First=11 , Second=22 } Removed Value: 11
Java collections framework
中HashMap
类提供了 哈希表数据结构
功能
它将元素存储在key/value
对中。此处,key是用于关联map上每个value的唯一标识符。
HashMap
类实现Map
接口
创建 HashMap 为了创建HashMap
,我们必须首先导入java.util.HashMap
包。导入包后,就可以使用Java创建HashMap
。
1 2 HashMap<K, V> numbers = new HashMap<>();
在上面代码中,我们创建了名为numbers
的hashmap.K
代表key,V
代表value.
1 HashMap<String, Integer> numbers = new HashMap<>();
上面例子中keys
类型是String
,values
类型是Integer
.
例子🌰 创建HashMap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> languages = new HashMap<>(); languages.put("Java" , 8 ); languages.put("JavaScript" , 1 ); languages.put("Python" , 3 ); System.out.println("HashMap: " + languages); } }
输出:
1 HashMap: {Java=8 , JavaScript=1 , Python=3 }
上面例子中我们创建了名为languages
的HashMap.我们用put(k,v)
向map
中添加元素。
Java中HashMap 基本操作 HashMap中基本操作分为四种:
HashMap 中新增元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> numbers = new HashMap<>(); System.out.println("Initial HashMap: " + numbers); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("HashMap after put(): " + numbers); } }
输出:
1 2 Initial HashMap: {} HashMap after put () : {One=1 , Two=2 , Three=3 }
在上面的示例中,我们创建了一个名为number
的HashMap。在这里,我们使用了put()
方法将元素添加到数字中。
其他添加元素方法:
获取一个元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("HashMap: " + languages); String value = languages.get(1 ); System.out.println("Value at index 1: " + value); } }
输出:
1 2 HashMap: {1 =Java, 2 =Python, 3 =JavaScript} Value at index 1 : Java
上面例子中:
在这里,get()方法将key
作为其参数,并返回与key
关联的相应value
。
通过keySet()
、values()
、entrySet()
获取keys
、values
、key/value
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("HashMap: " + languages); System.out.println("Keys: " + languages.keySet()); System.out.println("Values: " + languages.values()); System.out.println("Key/Value mappings: " + languages.entrySet()); } }
输出:
1 2 3 4 HashMap: {1 =Java, 2 =Python, 3 =JavaScript} Keys: [1 , 2 , 3 ] Values: [Java, Python, JavaScript] Key/Value mappings: [1 =Java, 2 =Python, 3 =JavaScript]
其他获取数据方法:
改变 HashMap值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("Original HashMap: " + languages); languages.replace(2 , "C++" ); System.out.println("HashMap using replace(): " + languages); } }
输出:
1 2 Original HashMap: {1 =Java, 2 =Python, 3 =JavaScript} HashMap using replace () : {1 =Java, 2 =C++, 3 =JavaScript}
将key是2
的值替换成了C++
.
其他修改值方法:
移除HashMap元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("HashMap: " + languages); String value = languages.remove(2 ); System.out.println("Removed value: " + value); System.out.println("Updated HashMap: " + languages); } }
输出:
1 2 3 HashMap: {1 =Java, 2 =Python, 3 =JavaScript} Removed value: Python Updated HashMap: {1 =Java, 3 =JavaScript}
在这里,remove()
方法将key作为其参数。然后,它返回与key关联的value并删除条目。
也可以在某中条件下删除数据
在此,只有key2
与valueC ++
关联时,remove()
方法才会删除该条目。由于2
与C ++
没有关联,因此它不会删除该条目。
其他 HashMap方法
遍历 HashMap 遍历HashMap
可以通过Java for-each loop
.我们可以遍历:keys
、values
、key/value
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import java.util.HashMap;import java.util.Map.Entry;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("HashMap: " + languages); System.out.print("Keys: " ); for (Integer key : languages.keySet()) { System.out.print(key); System.out.print(", " ); } System.out.print("\nValues: " ); for (String value : languages.values()) { System.out.print(value); System.out.print(", " ); } System.out.print("\nEntries: " ); for (Entry<Integer, String> entry : languages.entrySet()) { System.out.print(entry); System.out.print(", " ); } } }
输出:
1 2 3 4 HashMap: {1 =Java, 2 =Python, 3 =JavaScript} Keys: 1 , 2 , 3 , Values: Java, Python, JavaScript, Entries: 1 =Java, 2 =Python, 3 =JavaScript,
请注意,我们在上面的示例中使用了Map.Entry
.这是Map接口的嵌套类,该类返回map的视图(元素)。
为了使用此类,我们首先需要导入java.util.Map.Entry
包。
从其它Map 创建HashMap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.HashMap;import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> evenNumbers = new TreeMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); System.out.println("TreeMap: " + evenNumbers); HashMap<String, Integer> numbers = new HashMap<>(evenNumbers); numbers.put("Three" , 3 ); System.out.println("HashMap: " + numbers); } }
输出:
1 2 TreeMap: {Four=4 , Two=2 } HashMap: {Two=2 , Three=3 , Four=4 }
在上面的示例中,我们创建了一个名为evenNumbers
的TreeMap
。注意表达式:
1 numbers = new HashMap<>(evenNumbers)
在这里,我们使用TreeMap
创建一个名为number
的HashMap
。
注意:创建HashMap时,我们可以包括可选参数:容量和负载系数。
1 HashMap<K, V> numbers = new HashMap<>(8 , 0.6f );
8(容量是 8)
- 这意味着它可以存储8个条目。
0.6f(负载系数为0.6)
- 这意味着只要我们的哈希表填充了60%,条目将移至新的哈希表,其大小是原始哈希表的两倍.
如果未使用可选参数,则默认容量为16,默认负载系数为0.75。
Javacollections framework
中LinkedHashMap
类提供了Map接口的哈希表和链表实现。
LinkedHashMap
接口扩展了HashMap
类,以将其条目存储在哈希表中。它在内部维护所有条目之间的双向链接列表,以对条目进行排序。
创建 LinkedHashMap 为了创建LinkedHashMap
,我们必须首先导入java.util.LinkedHashMap
包。
1 2 LinkedHashMap<Key, Value> numbers = new LinkedHashMap<>(8 , 0.6f );
在上面的代码中,我们创建了一个名为Numbers
的LinkedHashMap
。
Key
- 用于关联map中每个元素(value)的唯一标识符
Value
- map中按key所关联的元素
注意新的LinkedHashMap <>(8,0.6)
部分。在这里,第一个参数是容量,第二个参数是负载系数。
8(容量是 8)
- 这意味着它可以存储8个条目。
0.6f(负载系数为0.6)
- 这意味着只要我们的哈希表填充了60%,条目将移至新的哈希表,其大小是原始哈希表的两倍.
如果未使用可选参数,则默认容量为16,默认负载系数为0.75。
注意: LinkedHashMap类还允许我们定义其条目的顺序。例如
1 2 LinkedHashMap<Key, Value> numbers2 = new LinkedHashMap<>(capacity, loadFactor, accessOrder);
在这里,accessOrder
是一个布尔值。其默认值为false
。在这种情况下,链接的哈希图中的条目将根据其插入顺序进行排序。
如果accessOrder
为true
,LinkedHashMap
中的条目将按从最近访问的顺序排列。
创建 LinkedHashMap 从另外一个 Map 创建一个包含其他map所有元素的LinkedHashMap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> evenNumbers = new LinkedHashMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); System.out.println("LinkedHashMap1: " + evenNumbers); LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(evenNumbers); numbers.put("Three" , 3 ); System.out.println("LinkedHashMap2: " + numbers); } }
输出:
1 2 LinkedHashMap1: {Two=2 , Four=4 } LinkedHashMap2: {Two=2 , Four=4 , Three=3 }
LinkedHashMap中的方法 插入元素
put()
- 将指定的key/value
映射插入到映射中
putAll()
-将指定map中的所有条目插入此map中
putIfAbsent()
- 如果map中不存在指定的key,则将指定的key/value
映射插入到map
中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> evenNumbers = new LinkedHashMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); System.out.println("Original LinkedHashMap: " + evenNumbers); evenNumbers.putIfAbsent("Six" , 6 ); System.out.println("Updated LinkedHashMap(): " + evenNumbers); LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(); numbers.put("One" , 1 ); numbers.putAll(evenNumbers); System.out.println("New LinkedHashMap: " + numbers); } }
输出:
1 2 3 Original LinkedHashMap: {Two=2 , Four=4 } Updated LinkedHashMap: {Two=2 , Four=4 , Six=6 } New LinkedHashMap: {One=1 , Two=2 , Four=4 , Six=6 }
获取元素
entrySet()
- 获取map中key/value
的集合
keySet()
- 获取map
中keys
的集合
values()
- 获取map
中values
的集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("LinkedHashMap: " + numbers); System.out.println("Key/Value mappings: " + numbers.entrySet()); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); } }
输出:
1 2 3 4 LinkedHashMap: {One=1 , Two=2 , Three=3 } Key/Value mappings: [One=1 , Two=2 , Three=3 ] Keys: [One, Two, Three] Values: [1 , 2 , 3 ]
get()
- 返回与指定key
关联的value
。如果找不到该键,则返回null
getOrDefault()
- 返回与指定key
关联的value
。 如果key
没有找到则返回默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("LinkedHashMap: " + numbers); int value1 = numbers.get("Three" ); System.out.println("Returned Number: " + value1); int value2 = numbers.getOrDefault("Five" , 5 ); System.out.println("Returned Number: " + value2); } }
输出:
1 2 3 LinkedHashMap: {One=1 , Two=2 , Three=3 } Returned Number: 3 Returned Number: 5
移除 LinkedHashMap中的元素
remove(key)
- 返回并从map中删除与指定key
关联的条目
remove(key, value)
- 当key
与value
匹配时才从map中删除,返回boolean值说明删除是否成功。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("LinkedHashMap: " + numbers); int value = numbers.remove("Two" ); System.out.println("Removed value: " + value); boolean result = numbers.remove("Three" , 3 ); System.out.println("Is the entry Three removed? " + result); System.out.println("Updated LinkedHashMap: " + numbers); } }
输出:
1 2 3 4 LinkedHashMap: {One=1 , Two=2 , Three=3 } Removed value: 2 Is the entry {Three=3 } removed? True Updated LinkedHashMap: {One=1 }
LinkedHashMap中其他方法
Method
Description
clear()
从map
上删除所有条目
containsKey()
检查map
是否包含指定的key
并返回布尔值
containsValue()
检查map
是否包含指定的value
并返回布尔值
size()
返回map大小
isEmpty()
检查map
是否为空并返回布尔值
LinkedHashMap Vs. HashMap LinkedHashMap
和HashMap
都实现Map接口,但它们存在一些差别
LinkedHashMap
在内部维护一个双向链接列表。因此,它保持其元素的插入顺序。
LinkedHashMap
类比`HashMap需要更多的存储空间。这是因为LinkedHashMap在内部维护链接列表。
LinkedHashMap
的性能比HashMap
慢。
Java collections framework
中的WeakHashMap类提供了哈希表数据结构的功能。
注意:weak hashmap中key是 弱引用
类型
如果引用不再在程序中使用,则弱引用
类型的对象可以在Java中被垃圾回收。
创建一个 WeakHashMap 为了创建一个weakHashMap
,我们必须首先导入java.util.WeakHashMap
包
1 2 WeakHashMap<Key, Value> numbers = new WeakHashMap<>(8 , 0.6 );
在上面的代码中,我们创建了一个名为Numbers
的WeakHashMap
。
Key
- 用于关联map中每个元素(value)的唯一标识符
Value
- map中按key所关联的元素
注意新的LinkedHashMap <>(8,0.6)
部分。在这里,第一个参数是容量,第二个参数是负载系数。
8(容量是 8)
- 这意味着它可以存储8个条目。
0.6f(负载系数为0.6)
- 这意味着只要我们的哈希表填充了60%,条目将移至新的哈希表,其大小是原始哈希表的两倍.
如果未使用可选参数,则默认容量为16,默认负载系数为0.75。
HashMap 和 WeakHashMap 让我们看看Java中weak Hash Map
的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String two = new String("Two" ); Integer twoValue = 2 ; String four = new String("Four" ); Integer fourValue = 4 ; numbers.put(two, twoValue); numbers.put(four, fourValue); System.out.println("WeakHashMap: " + numbers); two = null ; System.gc(); System.out.println("WeakHashMap after garbage collection: " + numbers); } }
输出:
1 2 WeakHashMap: {Four=4 , Two=2 } WeakHashMap after garbage collection: {Four}
如我们所见,当weakHashMap
中key
是2设置为null并执行垃圾回收时,该键将被删除。
因为与hashMap
不同,weakHashMap
中的key
是弱引用
类型。这意味着,如果不再使用映射条目,则垃圾收集器将删除该条目。这对于节省资源很有用。
现在让我们在hashMap
中查看相同的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> numbers = new HashMap<>(); String two = new String("Two" ); Integer twoValue = 2 ; String four = new String("Four" ); Integer fourValue = 4 ; numbers.put(two, twoValue); numbers.put(four, fourValue); System.out.println("HashMap: " + numbers); two = null ; System.gc(); System.out.println("HashMap after garbage collection: " + numbers); } }
输出:
1 2 HashMap: {Four=4 , Two=2 } HashMap after garbage collection: {Four=4 , Two=2 }
在这里,当hashMap
的key
是2设置为null并执行垃圾回收时,不会删除该键。
这是因为与weakHashMap
不同,hashMap
的key
具有强引用类型。这意味着垃圾回收器不会删除映射的条目,即使不再使用该条目的键。
hashMap
和weakHashMap
的所有功能都相似,只是weakHashMap
的键具有弱引用性,而hashMap
的键具有强引用性。
创建一个 WeakHashMap从其它Map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.HashMap;import java.util.WeakHashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> evenNumbers = new HashMap<>(); String two = new String("Two" ); Integer twoValue = 2 ; evenNumbers.put(two, twoValue); System.out.println("HashMap: " + evenNumbers); WeakHashMap<String, Integer> numbers = new WeakHashMap<>(evenNumbers); System.out.println("WeakHashMap: " + numbers); } }
输出:
1 2 HashMap: {Two=2 } WeakHashMap: {Two=2 }
WeakHashMap中的方法 插入元素
put()
- 将指定的key/value
插入到map
putAll()
- 将指定map中的所有条目插入此map中
putIfAbsent()
- 如果map中不存在指定的key,则将指定的key/value
映射插入到map
中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> evenNumbers = new WeakHashMap<>(); String two = new String("Two" ); Integer twoValue = 2 ; evenNumbers.put(two, twoValue); String four = new String("Four" ); Integer fourValue = 4 ; evenNumbers.putIfAbsent(four, fourValue); System.out.println("WeakHashMap of even numbers: " + evenNumbers); WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String one = new String("One" ); Integer oneValue = 1 ; numbers.put(one, oneValue); numbers.putAll(evenNumbers); System.out.println("WeakHashMap of numbers: " + numbers); } }
输出:
1 2 WeakHashMap of even numbers: {Four=4 , Two=2 } WeakHashMap of numbers: {Two=2 , Four=4 , One=1 }
获取元素
entrySet()
- 获取map中key/value
的集合
keySet()
- 获取map
中keys
的集合
values()
- 获取map
中values
的集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String one = new String("One" ); Integer oneValue = 1 ; numbers.put(one, oneValue); String two = new String("Two" ); Integer twoValue = 2 ; numbers.put(two, twoValue); System.out.println("WeakHashMap: " + numbers); System.out.println("Key/Value mappings: " + numbers.entrySet()); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); } }
输出:
1 2 3 4 WeakHashMap: {Two=2 , One=1 } Key/Value mappings: [Two=2 , One=1 ] Keys: [Two, One] Values: [1 , 2 ]
get()
- 返回与指定key
关联的value
。如果找不到该键,则返回null
getOrDefault()
- 返回与指定key
关联的value
。 如果key
没有找到则返回默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String one = new String("One" ); Integer oneValue = 1 ; numbers.put(one, oneValue); String two = new String("Two" ); Integer twoValue = 2 ; numbers.put(two, twoValue); System.out.println("WeakHashMap: " + numbers); int value1 = numbers.get("Two" ); System.out.println("Using get(): " + value1); int value2 = numbers.getOrDefault("Four" , 4 ); System.out.println("Using getOrDefault(): " + value2); } }
输出:
1 2 3 WeakHashMap: {Two=2 , One=1 } Using get () : 2 Using getOrDefault () : 4
移除元素
remove(key)
- 返回并从map中删除与指定key
关联的条目
remove(key, value)
- 当key
与value
匹配时才从map中删除,返回boolean值说明删除是否成功。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String one = new String("One" ); Integer oneValue = 1 ; numbers.put(one, oneValue); String two = new String("Two" ); Integer twoValue = 2 ; numbers.put(two, twoValue); System.out.println("WeakHashMap: " + numbers); int value = numbers.remove("Two" ); System.out.println("Removed value: " + value); boolean result = numbers.remove("One" , 3 ); System.out.println("Is the entry {One=3} removed? " + result); System.out.println("Updated WeakHashMap: " + numbers); } }
输出:
1 2 3 4 WeakHashMap: {Two=2 , One=1 } Removed value: 2 Is the entry {One=3 } removed? False Updated WeakHashMap: {One=1 }
WeakHashMap中其他方法
Method
Description
clear()
从map
上删除所有条目
containsKey()
检查map
是否包含指定的key
并返回布尔值
containsValue()
检查map
是否包含指定的value
并返回布尔值
size()
返回map大小
isEmpty()
检查map
是否为空并返回布尔值
java collections framework
的EnumMap
提供了在Map中实现枚举的能力。
在EnumMap
中,枚举元素用作keys
,它实现了Map接口。
创建一个 EnumMap 为了创建一个EnumMap
,我们必须首先导入java.util.EnumMap
包。
1 2 3 4 5 enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class);
在上面的示例中,我们创建了一个名为size
的EnumMap
。
Size
- map中的keys枚举值
Integer
- 与keys相关联的value值
EnumMap中的方法 插入元素
put()
- 将key/value
插入到EnumMap 中
putAll()
- 将指定的map数据全部插入到当前map中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes1 = new EnumMap<>(Size.class); sizes1.put(Size.SMALL, 28 ); sizes1.put(Size.MEDIUM, 32 ); System.out.println("EnumMap1: " + sizes1); EnumMap<Size, Integer> sizes2 = new EnumMap<>(Size.class); sizes2.putAll(sizes1); sizes2.put(Size.LARGE, 36 ); System.out.println("EnumMap2: " + sizes2); } }
输出:
1 2 EnumMap1: {SMALL=28 , MEDIUM=32 } EnumMap2: {SMALL=28 , MEDIUM=32 , LARGE=36 }
在上面的示例中,我们使用putAll()
方法将enum map
size1
的所有元素插入到enum map
size2
的中。
enum map的putAll()
还插入其他类型的map(HashMap
、TreeMap
).但是,所有map都应具有相同的枚举类型。
获取元素
entrySet()
- 返回一个enum map的所有key/value
映射(条目)的集合
keySet()
- 返回一个enum map中所有的keys
集合
values()
- 返回一个enum map中所有的values
集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class); sizes.put(Size.SMALL, 28 ); sizes.put(Size.MEDIUM, 32 ); sizes.put(Size.LARGE, 36 ); sizes.put(Size.EXTRALARGE, 40 ); System.out.println("EnumMap: " + sizes); System.out.println("Key/Value mappings: " + sizes.entrySet()); System.out.println("Keys: " + sizes.keySet()); System.out.println("Values: " + sizes.values()); } }
输出:
1 2 3 4 EnumMap: {SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 } Key/Value mappings: [SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 ] Keys: [SMALL, MEDIUM, LARGE, EXTRALARGE] Values: [28 , 32 , 36 , 40 ]
get(key)
- 指定的key
返回value
,如果key
不存在则返回null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class); sizes.put(Size.SMALL, 28 ); sizes.put(Size.MEDIUM, 32 ); sizes.put(Size.LARGE, 36 ); sizes.put(Size.EXTRALARGE, 40 ); System.out.println("EnumMap: " + sizes); int value = sizes.get(Size.MEDIUM); System.out.println("Value of MEDIUM: " + value); } }
输出:
1 2 EnumMap: {SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 } Value of MEDIUM: 32
移除元素
remove(key)
- 根据key
删除数据,如果删除成功则返回该数据
remove(key, value)
- 当map中存在key/value
匹配情况则删除,返回boolean类型值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class); sizes.put(Size.SMALL, 28 ); sizes.put(Size.MEDIUM, 32 ); sizes.put(Size.LARGE, 36 ); sizes.put(Size.EXTRALARGE, 40 ); System.out.println("EnumMap: " + sizes); int value = sizes.remove(Size.MEDIUM); System.out.println("Removed Value: " + value); boolean result = sizes.remove(Size.SMALL, 28 ); System.out.println("Is the entry {SMALL=28} removed? " + result); System.out.println("Updated EnumMap: " + sizes); } }
输出:
1 2 3 4 EnumMap: {SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 } Removed Value: 32 Is the entry {SMALL=28 } removed? True Updated EnumMap: {LARGE=36 , EXTRALARGE=40 }
替换元素
replace(key, value)
- 将key
对于的值替换成value
replace(key, old, new)
- 如果key
对于的值是old
则替换成new
replaceAll(function)
- 将map的每个值替换为指定函数的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class); sizes.put(Size.SMALL, 28 ); sizes.put(Size.MEDIUM, 32 ); sizes.put(Size.LARGE, 36 ); sizes.put(Size.EXTRALARGE, 40 ); System.out.println("EnumMap: " + sizes); sizes.replace(Size.MEDIUM, 30 ); sizes.replace(Size.LARGE, 36 , 34 ); System.out.println("EnumMap using replace(): " + sizes); sizes.replaceAll((key, oldValue) -> oldValue + 3 ); System.out.println("EnumMap using replaceAll(): " + sizes); } }
输出:
1 2 3 EnumMap: {SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 } EnumMap using replace () : {SMALL=28 , MEDIUM=30 , LARGE=34 , EXTRALARGE=40 }EnumMap using replaceAll () : {SMALL=31 , MEDIUM=33 , LARGE=37 , EXTRALARGE=43 }
EnumMap中其他方法
Method
Description
clone()
创建EnumMap
的副本
containsKey()
在EnumMap
中搜索指定的键,并返回一个布尔结果
containsValue()
在EnumMap
中搜索指定的值,并返回一个布尔结果
size()
返回EnumMap
的大小
clear()
从EnumMap
中删除所有条目
EnumSet Vs. EnumMap EnumSet
和EnumMap
类都提供数据结构来存储枚举值。但是,它们之间存在一些主要差异。
EnumSet
在内部以位序列表示,而EnumMap
在内部以数组表示。
EnumSet
是使用其预定义方法(例如allOf()
,noneOf()
,of()
),但是,EnumMap
是使用其构造函数创建的。
可克隆和可序列化的接口 EnumMap
类还实现了Cloneable
和Serializable
接口。
Cloneable 它允许EnumMap
类制作该类实例的副本。
Serializable 每当需要通过网络传输Java对象时,就需要将对象转换为位或字节。这是因为Java对象无法通过网络传输。
Serializable
接口允许对类进行序列化。这意味着可以将实现Serializable
的类的对象转换为位或字节。
Java collections framework
的SortedMap
接口可对存储在map
中的key
进行排序。
实现 SortedMap的类 由于SortedMap
是一个接口,因此无法从中创建对象。
为了使用SortedMap
接口的功能,我们需要使用实现该接口的类TreeMap
。
怎么使用SortedMap 要使用SortedMap
,我们必须首先导入java.util.SortedMap
包。
1 2 SortedMap<Key, Value> numbers = new TreeMap<>();
key
- 用于关联map中每个元素(值)的唯一标识符
Value
-map中按key
关联的元素
在这里,我们没有使用任何参数来创建排序的map,因此,map将自然排序(升序)。
SortedMap中的方法 SortedMap
接口包含Map
接口的所有方法。这是因为Map
是SortedMap
的超级接口。
除了所有这些方法之外,以下是SortedMap
接口专用的方法。
comparator() -返回一个可用于对map中的key进行排序的比较器
firstKey() - 返回已排序映射的第一个key
lastKey() - 返回已排序映射的最后一个key
headMap(key) - 返回其key小于指定key的map的所有条目
tailMap(key) - 返回其key大于或等于指定键的映射的所有条目
subMap(key1, key2) - 返回其key
位于key1
和key2
之间(包括key1
)的map的所有条目
TreeMap实现SortedMap类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.SortedMap;import java.util.TreeMap;class Main { public static void main (String[] args) { SortedMap<String, Integer> numbers = new TreeMap<>(); numbers.put("Two" , 2 ); numbers.put("One" , 1 ); System.out.println("SortedMap: " + numbers); System.out.println("First Key: " + numbers.firstKey()); System.out.println("Last Key: " + numbers.lastKey()); int value = numbers.remove("One" ); System.out.println("Removed Value: " + value); } }
输出:
1 2 3 4 SortedMap: {One=1 , Two=2 } First Key: One Last Key: Two Removed Value: 1
Java collections framework
的NavigableMap
提供了 map中数据互相导航的能力
NavigableMap
继承至SortedMap
实现NavigableMap的类 由于NavigableMap
是一个接口,因此我们无法从中创建对象。
为了使用NavigableMap
接口的功能,我们需要使用实现NavigableMap
的TreeMap
类。
怎么使用 NavigableMap 在Java中,我们必须导入java.util.NavigableMap
包才能使用NavigableMap
。
1 2 NavigableMap<Key, Value> numbers = new TreeMap<>();
在上面的代码中,我们创建了一个名为numbers
的TreeMap
类。
Key
- 用于关联map中每个元素(值)的唯一标识符
Value
- map中按key
关联的元素
NavigableMap中的方法 NavigableMap
被视为SortedMap
的一种。这是因为NavigableMap
扩展了SortedMap
接口。因此,所有的SortedMap
方法在NavigableMap
中也可用。
但是,在NavigableMap
中对SortedMap
的某些方法(headMap()
,tailMap()
和subMap()
)进行了不同的定义。
headMap(key, booleanValue) headMap()
会将navigable map
中key
之前所有keys
相关关联的数据返回。booleanValue
是一个可选参数,默认是true
如果booleanValue
是true
,表示该方法返回key
之前的keys
所有关联数据包括key
本身
tailMap(key, booleanValue) tailMap()
会将navigable map
中key
之后所有keys
相关关联的数据返回。booleanValue
是一个可选参数,默认是true
如果booleanValue
是个false
,则该方法返回key
之后keys
所有关联数据包括key
本身
subMap(k1, bv1, k2, bv2) subMap()
返回k1
与k2
之间所有的数据,包括k1
数据
bv1
和bv2
是可选参数。 bv1
的默认值为true
,bv2
的默认值为false
如果将bv1
设为false
,则返回k1
与k2
之间所有的数据,不包括k1
数据
如果将bv2
设为true
,则返回k1
与k2
之间所有的数据,包括k2
的数据
其它方法 NavigableMap
提供了各种用于设置数据在map中位置的方法。
descendingMap()
-反转map中的数据顺序
descendingKeyMap()
- 反转map中keys的顺序
ceilingEntry()
- 返回所有大于或等于指定key
中,最小key
关联的数据
ceilingKey()
- 返回所有大于或等于指定key
中,最小key
floorEntry()
- 返回所有小于或等于指定key
中,最大key
关联的数据
floorKey()
- 返回所有小于或等于指定key
中,最大key
higherEntry()
- 返回所有大于指定key
中,最小key
关联的数据
higherKey()
- 返回所有大于指定key
中,最小key
lowerEntry()
- 返回所有小于指定key
中,最大key
关联的数据
lowerKey()
- 返回所有小于指定key
中,最大的key
firstEntry()
- 返回map的第一个数据(具有最小key
的数据)
lastEntry()
- 返回map中最后一个数据(具有最大key
的数据)
pollFirstEntry()
- 返回并删除map中第一个数据
pollLastEntry()
- 返回并删除map中最后一个数据
NavigableMap 的实现 TreeMap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.NavigableMap;import java.util.TreeMap;class Main { public static void main (String[] args) { NavigableMap<String, Integer> numbers = new TreeMap<>(); numbers.put("Two" , 2 ); numbers.put("One" , 1 ); numbers.put("Three" , 3 ); System.out.println("NavigableMap: " + numbers); System.out.println("First Entry: " + numbers.firstEntry()); System.out.println("Last Entry: " + numbers.lastEntry()); System.out.println("Removed First Entry: " + numbers.pollFirstEntry()); System.out.println("Removed Last Entry: " + numbers.pollLastEntry()); } }
输出:
1 2 3 4 5 NavigableMap: {One=1 , Three=3 , Two=2 } First Entry: One=1 Last Entry: Two=2 Removed First Entry: One=1 Removed Last Entry: Two=2
Java collections framework
提供了 tree
数据结构的实现
创建 TreeMap 为了创建TreeMap
,我们必须首先导入java.util.TreeMap
包。
1 TreeMap<Key, Value> numbers = new TreeMap<>();
在上面的代码中,我们创建了一个名为Numbers
的TreeMap
,没有任何参数。在这种情况下,TreeMap
中的元素会自然排序(升序)。但是,我们可以使用Comparator
接口自定义元素的排序。
Key
- 用于关联map中每个元素(值)的唯一标识符
Value
- map中按key
关联的元素
TreeMap 中的方法 插入元素
put()
- 将指定的key/value
插入到map中
putAll()
- 将指定到map所有数据插入到当前map中
putIfAbsent()
- 如果map中不存在指定的key,则将指定的key/value
映射插入map中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> evenNumbers = new TreeMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); evenNumbers.putIfAbsent("Six" , 6 ); System.out.println("TreeMap of even numbers: " + evenNumbers); TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("One" , 1 ); numbers.putAll(evenNumbers); System.out.println("TreeMap of numbers: " + numbers); } }
输出:
1 2 TreeMap of even numbers: {Four=4 , Six=6 , Two=2 } TreeMap of numbers: {Four=4 , One=1 , Six=6 , Two=2 }
获取元素
entrySet()
- 返回 treemap中所有key/value
集合
keySet()
- 返回treemap中所有key
集合
values()
- 返回treemap中所有value
集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("TreeMap: " + numbers); System.out.println("Key/Value mappings: " + numbers.entrySet()); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); } }
输出:
1 2 3 4 TreeMap: {One=1 , Three=3 , Two=2 } Key/Value mappings: [One=1 , Three=3 , Two=2 ] Keys: [One, Three, Two] Values: [1 , 3 , 2 ]
get(key)
- 返回与指定key关联的value。如果找不到key,则返回null
。
getOrDefault(key,defalutValue)
- 返回与指定key
关联的value
。如果找不到key
,则返回指定的默认值(defalutValue
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("TreeMap: " + numbers); int value1 = numbers.get("Three" ); System.out.println("Using get(): " + value1); int value2 = numbers.getOrDefault("Five" , 5 ); System.out.println("Using getOrDefault(): " + value2); } }
输出:
1 2 3 TreeMap: {One=1 , Three=3 , Two=2 } Using get () : 3 Using getOrDefault () : 5
移除元素
remove(key)
- 返回并从TreeMap中删除与指定key
关联的数据
remove(key, value)
- 仅当指定key
与指定value
相关联时才从map中删除数据,并返回布尔值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("TreeMap: " + numbers); int value = numbers.remove("Two" ); System.out.println("Removed value: " + value); boolean result = numbers.remove("Three" , 3 ); System.out.println("Is the entry {Three=3} removed? " + result); System.out.println("Updated TreeMap: " + numbers); } }
输出:
1 2 3 4 TreeMap: {One=1 , Three=3 , Two=2 } Removed value = 2 Is the entry {Three=3 } removed? True Updated TreeMap: {One=1 }
替换元素
replace(key, value)
- 用新值value
替换key
关联的旧值
replace(key, old, new)
-仅当旧值已与指定key
关联时,才用新值替换旧值
replaceAll(function)
- 将map的每个value
替换为指定函数的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); System.out.println("Original TreeMap: " + numbers); numbers.replace("Second" , 22 ); numbers.replace("Third" , 3 , 33 ); System.out.println("TreeMap using replace: " + numbers); numbers.replaceAll((key, oldValue) -> oldValue + 2 ); System.out.println("TreeMap using replaceAll: " + numbers); } }
输出:
1 2 3 Original TreeMap: {First=1 , Second=2 , Third=3 } TreeMap using replace () : {First=1 , Second=22 , Third=33 }TreeMap using replaceAll () : {First=3 , Second=24 , Third=35 }
Navigation 中的方法 由于TreeMap
类实现了NavigableMap
,因此它提供了各种方法来浏览treemap
的元素。
First and Last Methods
firstKey()
- 返回 map 第一个key
firstEntry()
- 返回map 第一个key 的数据(key/value)
lastKey()
- 返回map最后一个key
lastEntry()
- 返回map最后一个key的数据(key/value)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); System.out.println("TreeMap: " + numbers); String firstKey = numbers.firstKey(); System.out.println("First Key: " + firstKey); String lastKey = numbers.lastKey(); System.out.println("Last Key: " + lastKey); System.out.println("First Entry: " + numbers.firstEntry()); System.out.println("Last Entry: " + numbers.lastEntry()); } }
输出:
1 2 3 4 5 TreeMap: {First=1 , Second=2 , Third=3 } First Key: First Last Key: Third First Entry: First=1 Last Entry: Third=3
Ceiling、Floor、Higher and Lower Methods
ceilingEntry()
- 返回所有大于或等于指定key
中,最小key
关联的数据
ceilingKey()
- 返回所有大于或等于指定key
中,最小key
floorEntry()
- 返回所有小于或等于指定key
中,最大key
关联的数据
floorKey()
- 返回所有小于或等于指定key
中,最大key
higherEntry()
- 返回所有大于指定key
中,最小key
关联的数据
higherKey()
- 返回所有大于指定key
中,最小key
lowerEntry()
- 返回所有小于指定key
中,最大key
关联的数据
lowerKey()
- 返回所有小于指定key
中,最大的key
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 5 ); numbers.put("Third" , 4 ); numbers.put("Fourth" , 6 ); System.out.println("TreeMap: " + numbers); System.out.println("Using higherKey(): " + numbers.higherKey("Fourth" )); System.out.println("Using higherEntry(): " + numbers.higherEntry("Fourth" )); System.out.println("\nUsing lowerKey(): " + numbers.lowerKey("Fourth" )); System.out.println("Using lowerEntry(): " + numbers.lowerEntry("Fourth" )); System.out.println("\nUsing ceilingKey(): " + numbers.ceilingKey("Fourth" )); System.out.println("Using ceilingEntry(): " + numbers.ceilingEntry("Fourth" )); System.out.println("\nUsing floorKey(): " + numbers.floorKey("Fourth" )); System.out.println("Using floorEntry(): " + numbers.floorEntry("Fourth" )); } }
输出:
1 2 3 4 5 6 7 8 9 10 11 12 TreeMap: {First=1 , Fourth=6 , Second=5 , Third=4 } Using higherKey () : Second Using higherEntry () : Second =5 Using lowerKey () : First Using lowerEntry () : First =1 Using ceilingKey () : Fourth Using ceilingEntry () : Fourth =6 Using floorkey () : Fourth Using floorEntry () : Fourth =6
pollFirstEntry() and pollLastEntry() Methods
pollFirstEntry()
- 返回并删除map中第一个数据
pollLastEntry()
- 返回并删除map中最后一个数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); System.out.println("TreeMap: " + numbers); System.out.println("Using pollFirstEntry(): " + numbers.pollFirstEntry()); System.out.println("Using pollLastEntry(): " + numbers.pollLastEntry()); System.out.println("Updated TreeMap: " + numbers); } }
输出:
1 2 3 4 TreeMap: {First=1 , Second=2 , Third=3 } Using pollFirstEntry () : First =1 Using pollLastEntry () : Third =3 Updated TreeMap: {Second=2 }
headMap(), tailMap() and subMap() Methods headMap(key,booleanValue)
headMap()
会将treemap
中key
之前所有keys
相关关联的数据返回。booleanValue
是一个可选参数,默认是true
如果booleanValue
是true
,表示该方法返回key
之前的keys
所有关联数据包括key
本身
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); numbers.put("Fourth" , 4 ); System.out.println("TreeMap: " + numbers); System.out.println("\nUsing headMap() Method:" ); System.out.println("Without boolean value: " + numbers.headMap("Fourth" )); System.out.println("With boolean value: " + numbers.headMap("Fourth" , true )); } }
输出:
1 2 3 4 5 TreeMap: {First=1 , Fourth=4 , Second=2 , Third=3 } Using headMap () Method: Without boolean value: {First=1 }With boolean value: {First=1 , Fourth=4 }
tailMap(key, booleanValue)
tailMap()
会将treemap
中key
之后所有keys
相关关联的数据返回。booleanValue
是一个可选参数,默认是true
如果booleanValue
是个false
,则该方法返回key
之后keys
所有关联数据包括key
本身
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); numbers.put("Fourth" , 4 ); System.out.println("TreeMap: " + numbers); System.out.println("\nUsing tailMap() Method:" ); System.out.println("Without boolean value: " + numbers.tailMap("Second" )); System.out.println("With boolean value: " + numbers.tailMap("Second" , false )); } }
输出:
1 2 3 4 5 TreeMap: {First=1 , Fourth=4 , Second=2 , Third=3 } Using tailMap () Method: Without boolean value: {Second=2 , Third=3 }With boolean value: {Third=3 }
subMap(k1, bV1, k2, bV2)
subMap()
返回k1
与k2
之间所有的数据,包括k1
数据
bv1
和bv2
是可选参数。 bv1
的默认值为true
,bv2
的默认值为false
如果将bv1
设为false
,则返回k1
与k2
之间所有的数据,不包括k1
数据
如果将bv2
设为true
,则返回k1
与k2
之间所有的数据,包括k2
的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); numbers.put("Fourth" , 4 ); System.out.println("TreeMap: " + numbers); System.out.println("\nUsing subMap() Method:" ); System.out.println("Without boolean value: " + numbers.subMap("Fourth" , "Third" )); System.out.println("With boolean value: " + numbers.subMap("Fourth" , false , "Third" , true )); } }
输出:
1 2 3 4 5 TreeMap: {First=1 , Fourth=2 , Second=2 , Third=3 } Using subMap () Method: Without boolean value: {Fourth=4 , Second=2 }With boolean value: {Second=2 , Third=3 }
其它方法
Method
Description
clone()
创建TreeMap的副本
containsKey()
在TreeMap中搜索指定的key
,并返回布尔结果
containsValue()
在TreeMap中搜索指定的value
并返回布尔结果
size()
返回TreeMap的大小
clear()
从TreeMap中删除所有条目
TreeMap Comparator treemap元素默认是自然排序(以升序排列)。但是,我们也可以自定义key
的顺序。
为此,我们需要基于treemap
中的key
排序来创建自己的比较器类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import java.util.TreeMap;import java.util.Comparator;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(new CustomComparator()); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); numbers.put("Fourth" , 4 ); System.out.println("TreeMap: " + numbers); } public static class CustomComparator implements Comparator <String > { @Override public int compare (String number1, String number2) { int value = number1.compareTo(number2); if (value > 0 ) { return -1 ; } else if (value < 0 ) { return 1 ; } else { return 0 ; } } } }
输出:
1 TreeMap: {Third=3 , Second=2 , Fourth=4 , First=1 }
在上面的示例中,我们创建了一个treemap
,将CustomComparator
类作为参数传递。
CustomComparator
类实现Comparator
接口。
然后,我们重写compare()
方法,以相反的顺序对元素进行排序。
Java collections framework
的concurrentMap
提供线程安全的map
.也就是说,多个线程可以一次访问map
,而不会影响映射中条目的一致性。
concurrentMap
被称为同步map
。
实现concurrentMap的 class concurrentMap
是个接口,我们不能通过它创建对象。
如果我们想使用concurrentMap
中的方法,我们需要使用concurrentHashMap
类,它是concurrentMap
的实现。
怎样使用 concurrentMap 要使用ConcurrentMap
,我们必须首先导入java.util.concurrent.ConcurrentMap
包。导入包后,将按照以下方法创建concurrentMap
。
1 2 ConcurrentMap<Key, Value> numbers = new ConcurrentHashMap<>();
在上面的代码中,我们创建了一个名为Numbers
的concurrentMap
。
Key
- 用于关联map
每个元素(value
)的唯一标识符.
Value
- map
中按key
关联的元素.
concurrentMap中的方法 ConcurrentMap
接口包含Map
接口的所有方法。这是因为Map
是ConcurrentMap
接口的超级接口。
除了所有这些方法外,以下是ConcurrentMap
接口特定的方法。
putIfAbsent()
- 如果指定的key/value
尚未与任何值关联,则将其插入到map
中。
compute()
- 计算指定key
的数据及其它之前的value
。
computeIfAbsent()
- 如果自定的key
尚未于map中任何value
有关联,则通过传入的函数计算一个value
与其关联。
computeIfPresent()
- 如果指定的key
有关联的value
,则计算一个新的值。
forEach()
- 访问map的所有条目并执行指定的操作。
merge()
- 如果key
已经映射到某个特定value
,则将新的指定value
与指定key
的旧值合并。如果该key
尚未映射,则该方法只需将指定的value
与我们的key
关联。
concurrentHashMap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.concurrent.ConcurrentMap;import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("Two" , 2 ); numbers.put("One" , 1 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentMap: " + numbers); int value = numbers.get("One" ); System.out.println("Accessed Value: " + value); int removedValue = numbers.remove("Two" ); System.out.println("Removed Value: " + removedValue); } }
输出:
1 2 3 ConcurrentMap: {One=1 , Two=2 , Three=3 } Accessed Value: 1 Removed Value: 2
Javacollections framework
的concurrentHashMap
类提供了线程安全的映射.也就是说,多个线程可以一次访问map,而不会影响map中数据的一致性。
创建concurrentHashMap 为了创建concurrentHashMao
,我们必须首先导入java.util.concurrent.ConcurrentHashMap
包。
1 2 ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8 , 0.6f );
Key
- 用于关联map
每个元素(value
)的唯一标识符.
Value
- map
中按key
关联的元素.
注意: ** ConcurrentHashMap <>(8,0.6)
部分。在这里,第一个参数是 容量,第二个参数是 负载系数**。
capacity - 该map的容量为 8。意味着,它可以存储8条数据。
loadFactor - map的负载系数是 0.6。它意味着当 hash table填充 60%时,会新增原 hash table 两倍数据量数据添加到原 hash table中。
默认 capacity 和 loadFactor 创建 concurrent hashmap
可以不定义 capacity
和 loadFactor
.
1 2 ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();
capacity
默认值是 16, loadFactor
默认值是 0.75.
通过另外的 map 创建 concurrentHashMap 这是我们如何创建包含其他映射的所有元素的concurrentHashMap
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.concurrent.ConcurrentHashMap;import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> evenNumbers = new HashMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); System.out.println("HashMap: " + evenNumbers); ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(evenNumbers); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); } }
输出:
1 2 HashMap: {Four=4 , Two=2 } ConcurrentHashMap: {Four=4 , Two=2 , Three=3 }
concurrentHashMap 中的方法 插入元素
put()
- 将指定的key/value
数据插入到map中
putAll()
- 将指定的map所有数据插入到当前map中
putIfAbsent()
- 如果map中不存在指定的key
,则将指定的key/value
插入到map中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); evenNumbers.putIfAbsent("Six" , 6 ); System.out.println("ConcurrentHashMap of even numbers: " + evenNumbers); ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.putAll(evenNumbers); System.out.println("ConcurrentHashMap of numbers: " + numbers); } }
输出:
1 2 ConcurrentHashMap of even numbers: {Six=6 , Four=4 , Two=2 } ConcurrentHashMap of numbers: {Six=6 , One=1 , Four=-4 , Two=2 }
获取元素
entrySet()
- 返回map的所有key/value
集合
keySet()
- 返回map所有的key
集合
valueSet()
- 返回map所有的value
集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); System.out.println("Key/Value mappings: " + numbers.entrySet()); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); } }
输出:
1 2 3 4 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Key/Value mappings: [One=1 , Two=2 , Three=3 ] Keys: [One, Two, Three] Values: [1 , 2 , 3 ]
get()
- 返回与指定key
关联的value
。如果找不到密钥,则返回null
。
getOrDefault()
- 返回与指定key
关联的value
。如果找不到密钥,则返回指定的默认值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); int value1 = numbers.get("Three" ); System.out.println("Using get(): " + value1); int value2 = numbers.getOrDefault("Five" , 5 ); System.out.println("Using getOrDefault(): " + value2); } }
输出:
1 2 3 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Using get () : 3 Using getOrDefault () : 5
移除元素
remove(key)
- 返回并从map中删除与指定key
关联的数据
remove(key, value)
- 仅在将指定key
映射到指定value
时在map中删除数据,并返回布尔值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); int value = numbers.remove("Two" ); System.out.println("Removed value: " + value); boolean result = numbers.remove("Three" , 3 ); System.out.println("Is the entry {Three=3} removed? " + result); System.out.println("Updated ConcurrentHashMap: " + numbers); } }
输出:
1 2 3 4 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Removed value: 2 Is the entry {Three=3 } removed? True Updated ConcurrentHashMap: {One=1 }
批量操作 concurrentHashMap concurrentHashMap
类提供了可以安全地应用于并发映射的不同批量操作。
forEach() 方法 forEach()
方法遍历我们的数据目并执行指定的函数。它包含两个参数:
parallelismThreshold
- 当数据量大于指定值时,进行并行计算。
transformer
- 进行值处理的回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); numbers.forEach(4 , (k, v) -> System.out.println("key: " + k + " value: " + v)); System.out.print("Values are " ); numbers.forEach(4 , (k, v) -> v, (v) -> System.out.print(v + ", " )); } }
输出:
1 2 3 4 5 ConcurrentHashMap: {One = 1 , Two = 2 , Three = 3 } key: One value: 1 key: Two value: 2 key: Three value: 3 Values are 1 , 2 , 3 ,
在上面的程序中,我们使用了并行阈值4。这意味着,如果map包含4个条目,则该操作将并行执行。
forEach() 变形方法
forEachEntry()
- 为每个数据执行指定的功能
forEachKey()
- 为每个key
执行指定的功能
forEachValue()
- 为每个value
执行指定的函数
search() 方法 search()
方法基于指定的函数搜索map,并返回匹配的条目。
在此,指定的功能确定要搜索的条目。
它还包括一个可选参数parallelThreshold
。并行阈值指定在map中有多少个元素之后并行执行该操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); String key = numbers.search(4 , (k, v) -> {return v == 3 ? k: null ;}); System.out.println("Searched value: " + key); } }
输出:
1 2 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Searched value: Three
search()的变形:
searchEntries()
- 搜索功能应用于key/value
映射
searchKeys()
- 搜索功能仅适用于key
searchValues()
- 搜索功能仅应用于value
reduce方法 reduce()
方法累积(聚集)映射中的每条数据。当我们需要所有条数据来执行一项常见任务(例如添加地图的所有值)时,可以使用此方法。它有连个参数:
parallelismThreshold
- 它指定在映射了几个元素之后,并行执行映射中的操作。
transformer
- 进行数据处理的回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); int sum = numbers.reduce(4 , (k, v) -> v, (v1, v2) -> v1 + v2); System.out.println("Sum of all values: " + sum); } }
输出:
1 2 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Sum of all values: 6
在上面的程序中,请注意以下语句:
1 numbers.reduce(4 , (k, v) -> v, (v1, v2) -> v1+v2);
4
- 并行阈值
(k,v) -> v
是转换函数。它将key/value
映射仅转换为value
。
(v1, v2) -> v1+v2
是一个累积函数。它收集所有value
并添加所有值。
reduce()变形方法
reduceEntries()
- 返回使用指定的reducer函数收集所有数据的结果
reduceKeys()
- 返回使用指定的reducer函数收集所有key
的结果
reduceValues()
- 返回使用指定的reducer函数收集所有value
的结果
ConcurrentHashMap vs HashMap 这是ConcurrentHashMap
和HashMap
之间的一些区别:
ConcurrentHashMap
是线程安全的集合。也就是说,多个线程可以同时访问和修改它。
ConcurrentHashMap
提供了用于批量操作的方法,例如forEach()
,search()
和reduce()
ConcurrentHashMap 优势
ConcurrentHashMap类允许多个线程同时访问数据。
默认情况下 concurrent hashmap是分为16段。这就是为什么允许16个线程同时并发修改映射的原因。但是,任何数量的线程一次都可以访问该map。
如果指定的key
已经存在,则putIfAbsent()
方法将不会覆盖映射中的数据。
它提供同步
Java collections framework
的Set
接口提供数学的集合 能力。它继承之collections
接口。
与List
接口不同,Set
不能包含重复的元素。
实现Set接口的类 由于Set
是接口,因此我们无法从中创建对象。
为了使用Set接口的功能,我们可以使用以下类:
继承Set的接口 这些子接口还扩展了Set接口:
怎么使用 Set 在Java中,我们必须导入java.util.Set
包才能使用Set
。
1 2 Set<String> animals = new HashSet<>();
在这里,我们创建了一个称为animals
的Set
。我们已经使用HashSet
类实现Set
接口。
Set中的方法 Set
接口包含Collection
接口的所有方法。
Set
接口中还提供了Collection
接口的一些常用方法:
add() - 将指定的元素添加到集合中
addAll() - 将指定集合的所有元素添加到集合中
iterator() - 返回一个迭代器,该迭代器可用于顺序访问集合中的元素
remove() - 从集合中移除指定的元素
removeAll() - 从存在于另一个指定集合中的集合中删除所有元素
retainAll() - 保留集合中也存在于另一个指定集合中的所有元素
clear() - 从集合中删除所有元素
size() - 返回集合的长度(元素数)
toArray() - 返回包含集合中所有元素的数组
contains() - 如果集合包含指定的元素,则返回true
containsAll() - 如果集合包含指定集合的所有元素,则返回true
hashCode() - 返回hash值(集合中元素的地址)
Set 操作符 Java Set接口允许我们执行基本的数学集合操作,例如并集,交集和子集。
Union - 要获得两个集合x和y的并集,我们可以使用x.addAll(y)
Intersection - 要获得两个集合x和y的交集,我们可以使用x.retainAll(y)
Subset - 要检查x是否是y的子集,我们可以使用y.containsAll(x)
Set接口的实现 HashSet 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.Set;import java.util.HashSet;class Main { public static void main (String[] args) { Set<Integer> set1 = new HashSet<>(); set1.add(2 ); set1.add(3 ); System.out.println("Set1: " + set1); Set<Integer> set2 = new HashSet<>(); set2.add(1 ); set2.add(2 ); System.out.println("Set2: " + set2); set2.addAll(set1); System.out.println("Union is: " + set2); } }
输出:
1 2 3 Set1: [2 , 3 ] Set2: [1 , 2 ] Union is: [1 , 2 , 3 ]
TreeSet 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.Set;import java.util.TreeSet;import java.util.Iterator;class Main { public static void main (String[] args) { Set<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(3 ); numbers.add(1 ); System.out.println("Set using TreeSet: " + numbers); System.out.print("Accessing elements using iterator(): " ); Iterator<Integer> iterate = numbers.iterator(); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 Set using TreeSet: [1 , 2 , 3 ] Accessing elements using iterator () : 1, 2, 3,
Java Collections framework
的HashSet
类提供了hash table结构的功能。
创建 HashSet 为了创建hash set
,我们必须首先导入java.util.HashSet
包。
1 2 HashSet<Integer> numbers = new HashSet<>(8 , 0.75 );
注意,新的HashSet <>(8,0.75)
部分。在这里,第一个参数是容量,第二个参数是负载系数。
capacity
- 该hash st
的容量为8。意味着,它可以存储8个元素。
loadFactor
- 此hash set
的负载系数为0.6。这意味着,只要我们的哈希集填充了60%,元素将移至新哈希表,其大小是原始哈希表的两倍。
默认 capacity 和 load factor 1 2 HashSet<Integer> numbers1 = new HashSet<>();
HashSet中的方法 插入元素
add()
- 将指定的元素插入集合
addAll()
- 将指定集合的所有元素插入集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> evenNumber = new HashSet<>(); evenNumber.add(2 ); evenNumber.add(4 ); evenNumber.add(6 ); System.out.println("HashSet: " + evenNumber); HashSet<Integer> numbers = new HashSet<>(); numbers.addAll(evenNumber); numbers.add(5 ); System.out.println("New HashSet: " + numbers); } }
输出:
1 2 HashSet: [2 , 4 , 6 ] New HashSet: [2 , 4 , 5 , 6 ]
获取元素 要访问hashset
的元素,我们可以使用iterator()
方法。为了使用此方法,我们必须导入java.util.Iterator
包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.HashSet;import java.util.Iterator;class Main { public static void main (String[] args) { HashSet<Integer> numbers = new HashSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("HashSet: " + numbers); Iterator<Integer> iterate = numbers.iterator(); System.out.print("HashSet using Iterator: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 HashSet: [2 , 5 , 6 ] HashSet using Iterator: 2 , 5 , 6 ,
移除元素
remvoe()
- 从set
中移除指定的元素
removeAll()
- 从set
中删除所有元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> numbers = new HashSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("HashSet: " + numbers); boolean value1 = numbers.remove(5 ); System.out.println("Is 5 removed? " + value1); boolean value2 = numbers.removeAll(numbers); System.out.println("Are all elements removed? " + value2); } }
输出:
1 2 3 HashSet: [2 , 5 , 6 ] Is 5 removed? true Are all elements removed? true
Set 操作符 HashSet
类的各种方法也可以用于执行各种设置操作。
Union 操作 两个执行两个集合之间的联合,我们可以使用addAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> evenNumbers = new HashSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("HashSet1: " + evenNumbers); HashSet<Integer> numbers = new HashSet<>(); numbers.add(1 ); numbers.add(3 ); System.out.println("HashSet2: " + numbers); numbers.addAll(evenNumbers); System.out.println("Union is: " + numbers); } }
输出:
1 2 3 HashSet1: [2 , 4 ] HashSet2: [1 , 3 ] Union is: [1 , 2 , 3 , 4 ]
Intersection 操作 为了执行两个集合之间的交集,我们可以使用retainAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> primeNumbers = new HashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("HashSet1: " + primeNumbers); HashSet<Integer> evenNumbers = new HashSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("HashSet2: " + evenNumbers); evenNumbers.retainAll(primeNumbers); System.out.println("Intersection is: " + evenNumbers); } }
输出:
1 2 3 HashSet1: [2 , 3 ] HashSet2: [2 , 4 ] Intersection is: [2 ]
Difference 操作 要计算两组之间的差异,我们可以使用removeAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> primeNumbers = new HashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); primeNumbers.add(5 ); System.out.println("HashSet1: " + primeNumbers); HashSet<Integer> oddNumbers = new HashSet<>(); oddNumbers.add(1 ); oddNumbers.add(3 ); oddNumbers.add(5 ); System.out.println("HashSet2: " + oddNumbers); primeNumbers.removeAll(oddNumbers); System.out.println("Difference : " + primeNumbers); } }
输出:
1 2 3 HashSet1: [2 , 3 , 5 ] HashSet2: [1 , 3 , 5 ] Difference: [2 ]
Subset 为了检查一个集合是否是另一个集合的子集,我们可以使用containsAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> numbers = new HashSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("HashSet1: " + numbers); HashSet<Integer> primeNumbers = new HashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("HashSet2: " + primeNumbers); boolean result = numbers.containsAll(primeNumbers); System.out.println("Is HashSet2 is subset of HashSet1? " + result); } }
输出:
1 2 3 HashSet1: [1 , 2 , 3 , 4 ] HashSet2: [2 , 3 ] Is HashSet2 is a subset of HashSet1? true
其它HashSet 方法
Method
Description
clone()
创建HashSet
的副本
contains()
在HashSet
中搜索指定的元素并返回布尔结果
isEmpty()
检查`HashSet是否为空
size()
返回HashSet
的大小
clear()
从HashSet
中删除所有元素
HashSet 好处 在Java中,如果我们必须随机访问元素,则通常使用HashSet
。这是因为使用哈希码访问哈希表中的元素。
元素的hashcode
是唯一的标识,有助于标识哈希表中的元素。
HashSet
不能包含重复的元素。因此,每个哈希集元素都有一个唯一的哈希码。
注意:HashSet不同步。也就是说,如果多个线程同时访问哈希集,并且其中一个线程修改了哈希集。然后必须从外部进行同步
Javacollections framework
的EnumSet
类提供单个枚举元素的固定实现。
创建 EnumSet 为了创建一个枚举集,我们必须首先导入java.util.EnumSet
包。
与其他集合实现不同,枚举集合没有公共构造函数。我们必须使用预定义的方法来创建一个枚举集。
allOf(Size) allof()
方法创建一个枚举集,其中包含指定枚举类型Size的所有值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.allOf(Size.class); System.out.println("EnumSet: " + sizes); } }
输出:
1 EnumSet: [SMALL, MEDIUM, LARGE, EXTRALARGE]
注意:
1 EnumSet<Size> sizes = EnumSet.allOf(Size.class);
在这里,Size.class
表示我们创建的Size
枚举。
noneOf(size) noneOf()
方法创建一个空的枚举集。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.noneOf(Size.class); System.out.println("Empty EnumSet: " + sizes); } }
输出:
在这里,我们创建了一个空的枚举,名为sizes
。
注意: 我们只能在上述程序中插入枚举类型为Size的元素。这是因为我们使用Size枚举创建了空的枚举集。
range(e1, e2) range()
方法创建一个枚举集,其中包含e1
和e2
之间的枚举的所有值,包括两个值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.range(Size.MEDIUM, Size.EXTRALARGE); System.out.println("EnumSet: " + sizes); } }
输出:
1 EnumSet: [MEDIUM, LARGE, EXTRALARGE]
of() of()
方法创建一个包含指定元素的枚举集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes1 = EnumSet.of(Size.MEDIUM); System.out.println("EnumSet1: " + sizes1); EnumSet<Size> sizes2 = EnumSet.of(Size.SMALL, Size.LARGE); System.out.println("EnumSet2: " + sizes2); } }
输出:
1 2 EnumSet1: [MEDIUM] EnumSet2: [SMALL, LARGE]
EnumSet 中方法 插入元素
add()
- 将指定的枚举值插入到枚举集中
addAll()
- 将指定集合的所有元素插入集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes1 = EnumSet.allOf(Size.class); EnumSet<Size> sizes2 = EnumSet.noneOf(Size.class); sizes2.add(Size.MEDIUM); System.out.println("EnumSet Using add(): " + sizes2); sizes2.addAll(sizes1); System.out.println("EnumSet Using addAll(): " + sizes2); } }
输出:
1 2 EnumSet using add () : [MEDIUM] EnumSet using addAll () : [SMALL, MEDIUM, LARGE, EXTRALARGE]
在上面的示例中,我们使用addAll()
方法将枚举集size1
的所有元素插入到枚举集size2
中。
也可以使用addAll()
将其他集合中的元素(例如ArrayList
,LinkedList
等)插入到枚举集中。
获取元素 要访问一个枚举集的元素,我们可以使用iterator()
方法。为了使用此方法,我们必须导入java.util.Iterator
包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.EnumSet;import java.util.Iterator;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.allOf(Size.class); Iterator<Size> iterate = sizes.iterator(); System.out.print("EnumSet: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 EnumSet: SMALL, MEDIUM, LARGE, EXTRALARGE
注意:
hasNext()
- 如果枚举集中存在下一个元素,则返回true
next()
- 返回枚举集中的下一个元素
remove
remove()
- 从枚举集中删除指定的元素
removeAll()
- 从枚举集中删除所有元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.allOf(Size.class); System.out.println("EnumSet: " + sizes); boolean value1 = sizes.remove(Size.MEDIUM); System.out.println("Is MEDIUM removed? " + value1); boolean value2 = sizes.removeAll(sizes); System.out.println("Are all elements removed? " + value2); } }
输出:
1 2 3 EnumSet: [SMALL, MEDIUM, LARGE, EXTRALARGE] Is MEDIUM removed? true Are all elements removed? true
其它方法
Method
Description
copyOf()
创建EnumSet的副本
contains()
在EnumSet中搜索指定的元素并返回布尔结果
isEmpty()
检查EnumSet是否为空
size()
返回EnumSet的大小
clear()
从EnumSet中删除所有元素
Clonable 和 Serializable 接口 EnumSet
类还实现了Cloneable
和Serializable
接口。
Clonable
它允许EnumSet
类制作该类实例的副本。
Serializable
每当需要通过网络传输Java对象时,就需要将对象转换为位或字节。这是因为Java对象无法通过网络传输。Serializable
接口允许对类进行序列化。这意味着可以将实现Serializable的类的对象转换为位或字节。
EnumSet 好处 与其他set实现(例如HashSet
,TreeSet
)相比,EnumSet提供了一种存储枚举值的有效方法。
枚举集仅存储特定枚举的枚举值。因此,JVM已经知道该集合的所有可能值。
这就是为什么枚举集在内部被实现为一系列Bits的原因。Bits指定元素是否存在于枚举集中。
如果集合中存在该元素,则将其对应的位打开。
Javacollections framework
的LinkedHashSet
类提供了哈希表和链表数据结构的功能。
LinkedHashSet
的元素存储在类似于HashSet的哈希表中
但是,LinkedHashSet
在内部为其所有元素维护一个双链表。链表定义了在哈希表中插入元素的顺序。
创建 LinkedHashSet 为了创建链接的哈希集,我们必须首先导入java.util.LinkedHashSet
包。
1 2 LinkedHashSet<Integer> numbers = new LinkedHashSet<>(8 , 0.75 );
注意,新的LinkedHashSet <>(8,0.75)
部分。在这里,第一个参数是容量,第二个参数是负载系数。
capacity - 该哈希集的容量为8。意味着,它可以存储8个元素。
loadFactor - 此哈希集的负载系数为0.6。这意味着,只要我们的哈希表填充了60%,元素就会移到新哈希表中,其大小是原始哈希表的两倍。
注意:capacity
和 loadFactor
默认值分别是 16,0.75;
LinkedHashSet 中的方法 LinkedHashSet
类提供的方法使我们可以对链表的哈希集执行各种操作。
插入元素
add()
- 将指定的元素插入到链表的哈希集中
addAll()
- 将指定集合的所有元素插入到链接的哈希集中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> evenNumber = new LinkedHashSet<>(); evenNumber.add(2 ); evenNumber.add(4 ); evenNumber.add(6 ); System.out.println("LinkedHashSet: " + evenNumber); LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.addAll(evenNumber); numbers.add(5 ); System.out.println("New LinkedHashSet: " + numbers); } }
输出:
1 2 LinkedHashSet: [2 , 4 , 6 ] New LinkedHashSet: [2 , 4 , 6 , 5 ]
获取元素 要访问链表的哈希集的元素,我们可以使用iterator()
方法。为了使用此方法,我们必须导入java.util.Iterator
包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.LinkedHashSet;import java.util.Iterator;class Main { public static void main (String[] args) { LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("LinkedHashSet: " + numbers); Iterator<Integer> iterate = numbers.iterator(); System.out.print("LinkedHashSet using Iterator: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 LinkedHashSet: [2 , 5 , 6 ] LinkedHashSet using Iterator: 2 , 5 , 6 ,
注意:
hasNext()
- 如果LinkedHashSet
中存在下一个元素,则返回true.
next()
- 返回LinkedHashSet
中的下一个元素
移除元素
remove()
- 从LinkedHashSet
中删除指定的元素
removeAll()
-从LinkedHashSet
中删除所有的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("LinkedHashSet: " + numbers); boolean value1 = numbers.remove(5 ); System.out.println("Is 5 removed? " + value1); boolean value2 = numbers.removeAll(numbers); System.out.println("Are all elements removed? " + value2); } }
输出:
1 2 3 LinkedHashSet: [2 , 5 , 6 ] Is 5 removed? true Are all elements removed? true
Set 操作符 LinkedHashSet
类的各种方法也可以用于执行各种集合操作。
Union 两个执行两个集合之间的联合,我们可以使用addAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> evenNumbers = new LinkedHashSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("LinkedHashSet1: " + evenNumbers); LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.add(1 ); numbers.add(3 ); System.out.println("LinkedHashSet2: " + numbers); numbers.addAll(evenNumbers); System.out.println("Union is: " + numbers); } }
输出:
1 2 3 LinkedHashSet1: [2 , 4 ] LinkedHashSet2: [1 , 3 ] Union is: [1 , 3 , 2 , 4 ]
Intersection 为了执行两个集合之间的交集,我们可以使用retainAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("LinkedHashSet1: " + primeNumbers); LinkedHashSet<Integer> evenNumbers = new LinkedHashSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("LinkedHashSet2: " + evenNumbers); evenNumbers.retainAll(primeNumbers); System.out.println("Intersection is: " + evenNumbers); } }
输出:
1 2 3 LinkedHashSet1: [2 , 3 ] LinkedHashSet2: [2 , 4 ] Intersection is: [2 ]
Difference 要计算两组之间的差异,我们可以使用removeAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); primeNumbers.add(5 ); System.out.println("LinkedHashSet1: " + primeNumbers); LinkedHashSet<Integer> oddNumbers = new LinkedHashSet<>(); oddNumbers.add(1 ); oddNumbers.add(3 ); oddNumbers.add(5 ); System.out.println("LinkedHashSet2: " + oddNumbers); primeNumbers.removeAll(oddNumbers); System.out.println("Difference : " + primeNumbers); } }
输出:
1 2 3 LinkedHashSet1: [2 , 3 , 5 ] LinkedHashSet2: [1 , 3 , 5 ] Difference: [2 ]
Subset 为了检查一个集合是否是另一个集合的子集,我们可以使用containsAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("LinkedHashSet1: " + numbers); LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("LinkedHashSet2: " + primeNumbers); boolean result = numbers.containsAll(primeNumbers); System.out.println("Is LinkedHashSet2 is subset of LinkedHashSet1? " + result); } }
输出:
1 2 3 LinkedHashSet1: [1 , 2 , 3 , 4 ] LinkedHashSet2: [2 , 3 ] Is LinkedHashSet2 is a subset of LinkedHashSet1? true
LinkedHashSet其它方法
Method
Description
clone()
创建 LinkedHashSet
副本
contains()
在LinkedHashSet
中搜索指定的元素,并返回布尔结果
isEmpty()
检查LinkedHashSet
是否为空
size()
返回`LinkedHashSet的大小
clear()
从LinkedHashSet
中删除所有元素
LinkedHashSet Vs. HashSet LinkedHashSet和HashSet都实现Set接口。但是,它们之间存在一些差异。
LinkedHashSet
在内部维护一个链表。因此,它保持其元素的插入顺序。
LinkedHashSet
类比HashSet
需要更多的存储空间。这是因为LinkedHashSet
在内部维护链接列表。
LinkedHashSet
的性能比HashSet
慢。这是因为LinkedHashSet
中存在链表。
LinkedHashSet Vs. TreeSet 这是LinkedHashSet
和TreeSet
之间的主要区别:
TreeSet
类实现SortedSet
接口。
TreeSet
通常比LinkedHashSet
慢。这是因为每当元素添加到TreeSet
时,它都必须执行排序操作。
LinkedHashSet
允许插入空值。但是,我们不能将空值插入`TreeSet。
Java collections framework
的SortedSet
接口用于将元素以某种顺序存储在集合中。
实现SortedSet的类 为了使用SortedSet
接口的功能,我们需要使用实现该接口的TreeSet
类。
怎么使用 SortedSet 要使用SortedSet
,我们必须首先导入java.util.SortedSet
包。
1 2 SortedSet<String> animals = new TreeSet<>();
在这里,我们没有使用任何参数来创建排序集。因此,该集合将自然排序。
SortedSet中的方法 SortedSet
接口包含Set
接口的所有方法。这是因为Set
是SortedSet
的超级接口。
除了Set
接口中包含的方法外,SortedSet
接口还包括以下方法:
comparator() - 返回一个比较器,该比较器可用于对集合中的元素进行排序
first() - 返回集合的第一个元素
last() - 返回集合的最后一个元素
headSet(element) - 返回指定元素之前的所有元素
tailSet(element) - 在指定元素之后(包括指定元素)返回集合中的所有元素
subSet(element1, element2) - 返回element1和element2之间的所有元素,包括element1
实现SortedSet的类 TreeSet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.SortedSet;import java.util.TreeSet;class Main { public static void main (String[] args) { SortedSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("SortedSet: " + numbers); int firstNumber = numbers.first(); System.out.println("First Number: " + firstNumber); int lastNumber = numbers.last(); System.out.println("Last Number: " + lastNumber); boolean result = numbers.remove(2 ); System.out.println("Is the number 2 removed? " + result); } }
输出:
1 2 3 4 SortedSet: [1 , 2 , 3 , 4 ] First Number: 1 Last Number: 4 Is the number 2 removed? true
Java Collections framework
的NavigableSet
接口提供了在集合之间导航的功能。
实现NavigableSet的类 为了使用NavigableSet
接口的功能,我们需要使用实现NavigableSet
的TreeSet
类。
怎么使用 NavigableSet 在Java中,我们必须导入java.util.NavigableSet
包才能使用NavigableSet
。
1 2 NavigableSet<String> numbers = new TreeSet<>();
NavigableSet中的方法 NavigableSet
被视为SortedSet
的一种。这是因为NavigableSet
扩展了SortedSet
接口。
但是,在NavigableSet中,对SortedSet的某些方法(headSet()
,tailSet()
和subSet()
)进行了不同的定义。
headSet(element, booleanValue) headSet()
方法返回指定元素之前的可导航集合的所有元素(作为参数传递)。booleanValue参数是可选的。其默认值为false。如果将true
作为booleanValue
传递,则该方法返回指定元素之前的所有元素,包括指定元素。
tailSet(element, booleanValue) tailSet()
方法在包含指定元素的指定元素(作为参数传递)之后返回可导航集中的所有元素。
booleanValue
参数是可选的。其默认值为true
。
如果将false
作为booleanValue
传递,则该方法返回指定元素之后的所有元素,而不包括指定元素。
subSet(e1,bv1,e2,bv2) subSet()
方法返回e1
和e2
之间的所有元素,包括e1
。
bv1
和bv2
是可选参数。 bv1
的默认值为true
,bv2
的默认值为false
。
如果将false
作为bv1
传递,则该方法返回e1
和e2
之间的所有元素,而不包括e1
。
如果将true
作为bv2
传递,则该方法返回e1
和e2
之间的所有元素,包括e1
。
Navigation 中的方法 NavigableSet提供了各种可用于导航其元素的方法。
descendingSet() - 反转集合中元素的顺序
descendingIterator() - 返回一个迭代器,该迭代器可用于以相反的顺序迭代集合
ceiling() - 返回大于或等于指定元素的那些元素中的最低元素
floor() - 返回小于或等于指定元素的那些元素中最大的元素
higher() - 返回大于指定元素的那些元素中的最低元素
lower() - 返回小于指定元素的那些元素中最大的元素
pollFirst() - 返回并从集合中删除第一个元素
pollLast() - 返回并从集合中删除最后一个元素
实现 NavigableSet接口的类TreeSet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import java.util.NavigableSet;import java.util.TreeSet;class Main { public static void main (String[] args) { NavigableSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("NavigableSet: " + numbers); int firstElement = numbers.first(); System.out.println("First Number: " + firstElement); int lastElement = numbers.last(); System.out.println("Last Element: " + lastElement); int number1 = numbers.pollFirst(); System.out.println("Removed First Element: " + number1); int number2 = numbers.pollLast(); System.out.println("Removed Last Element: " + number2); } }
输出:
1 2 3 4 5 NavigableSet: [1 , 2 , 3 ] First Element: 1 Last Element: 3 Removed First Element: 1 Removed Last Element: 3
Java collections framework
的TreeSet
类提供树数据结构的功能。
创建 TreeSet 为了创建树集,我们必须首先导入java.util.TreeSet
包。
1 TreeSet<Integer> numbers = new TreeSet<>();
在这里,我们创建了一个不带任何参数的TreeSet
。在这种情况下,TreeSet
中的元素会自然排序(升序)。
但是,我们可以使用Comparator
接口自定义元素的排序。
TreeSet中的方法 TreeSet类提供了各种方法,使我们可以对集合执行各种操作。
插入元素
add()
- 将指定的元素插入集合
addAll()
- 将指定集合的所有元素插入集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> evenNumbers = new TreeSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); evenNumbers.add(6 ); System.out.println("TreeSet: " + evenNumbers); TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.addAll(evenNumbers); System.out.println("New TreeSet: " + numbers); } }
输出:
1 2 TreeSet: [2 , 4 , 6 ] New TreeSet: [1 , 2 , 4 , 6 ]
获取元素 要访问树集的元素,我们可以使用iterator()
方法。为了使用此方法,我们必须导入java.util.Iterator
包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;import java.util.Iterator;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); Iterator<Integer> iterate = numbers.iterator(); System.out.print("TreeSet using Iterator: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 TreeSet: [2 , 5 , 6 ] TreeSet using Iterator: 2 , 5 , 6 ,
删除元素
remove()
- 从集合中移除指定的元素
removeAll()
- 从集合中删除所有元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); boolean value1 = numbers.remove(5 ); System.out.println("Is 5 removed? " + value1); boolean value2 = numbers.removeAll(numbers); System.out.println("Are all elements removed? " + value2); } }
输出:
1 2 3 TreeSet: [2 , 5 , 6 ] Is 5 removed? true Are all elements removed? true
Navigation中的方法 由于TreeSet
类实现了NavigableSet
,因此它提供了各种方法来浏览树集的元素。
first() and last()
first()
- 返回集合的第一个元素
last()
- 返回集合的最后一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); int first = numbers.first(); System.out.println("First Number: " + first); int last = numbers.last(); System.out.println("Last Number: " + last); } }
输出:
1 2 3 TreeSet: [2 , 5 , 6 ] First Number: 2 Last Number: 6
ceiling(), floor(), higher() and lower()
higher(element) - 返回大于指定元素的那些元素中的最低元素
lower(element) - 返回小于指定元素的那些元素中最大的元素
ceiling(element) - 返回大于指定元素的那些元素中的最低元素, 如果传递的元素存在于树集中,则返回作为参数传递的元素.
floor(element) - 返回小于指定元素的那些元素中最大的元素, 如果传递的元素存在于树集中,则返回作为参数传递的元素.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Using higher: " + numbers.higher(4 )); System.out.println("Using lower: " + numbers.lower(4 )); System.out.println("Using ceiling: " + numbers.ceiling(4 )); System.out.println("Using floor: " + numbers.floor(3 )); } }
输出:
1 2 3 4 5 TreeSet: [2 , 4 , 5 , 6 ] Using higher: 5 Using lower: 2 Using ceiling: 4 Using floor: 2
pollfirst() and pollLast()
pollFirst()
- 返回并从集合中删除第一个元素
pollLast()
- 返回并从集合中删除最后一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Removed First Element: " + numbers.pollFirst()); System.out.println("Removed Last Element: " + numbers.pollLast()); System.out.println("New TreeSet: " + numbers); } }
输出:
1 2 3 4 TreeSet: [2 , 4 , 5 , 6 ] Removed First Element: 2 Removed Last Element: 6 New TreeSet: [4 , 5 ]
headSet(element, booleanValue) headSet()
方法返回指定元素(作为参数传递)之前的树集的所有元素。booleanValue
参数是可选的。其默认值为false
。
如果将true
作为booleanValue
传递,则该方法返回指定元素之前的所有元素,包括指定元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Using headSet without boolean value: " + numbers.headSet(5 )); System.out.println("Using headSet with boolean value: " + numbers.headSet(5 , true )); } }
输出:
1 2 3 TreeSet: [2 , 4 , 5 , 6 ] Using headSet without boolean value: [2 , 4 ] Using headSet with boolean value: [2 , 4 , 5 ]
tailSet(element, booleanValue) tailSet()
方法返回包含指定元素的指定元素(作为参数传递)之后的树集的所有元素.booleanValue
参数是可选的。其默认值为true
。
如果将false
作为booleanValue
传递,则该方法返回指定元素之后的所有元素,而不包括指定元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Using tailSet without boolean value: " + numbers.tailSet(4 )); System.out.println("Using tailSet with boolean value: " + numbers.tailSet(4 , false )); } }
输出:
1 2 3 TreeSet: [2 , 4 , 5 , 6 ] Using tailSet without boolean value: [4 , 5 , 6 ] Using tailSet with boolean value: [5 , 6 ]
subSet(e1, bv1, e2, bv2) subSet()
方法返回e1
和e2
之间的所有元素,包括e1
。
bv1
和bv2
是可选参数。 bv1
的默认值为true
,bv2
的默认值为false
。
如果将false
作为bv1
传递,则该方法返回e1
和e2
之间的所有元素,而不包括e1
。
如果将true
作为bv2
传递,则该方法返回e1
和e2
之间的所有元素,包括e1
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Using subSet without boolean value: " + numbers.subSet(4 , 6 )); System.out.println("Using subSet with boolean value: " + numbers.subSet(4 , false , 6 , true )); } }
输出:
1 2 3 TreeSet: [2 , 4 , 5 , 6 ] Using subSet without boolean value: [4 , 5 ] Using subSet with boolean value: [5 , 6 ]
集合操作符 TreeSet
类的方法还可用于执行各种集合操作。
Union 为了执行两个集合之间的联合,我们使用addAll()
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;;class Main { public static void main (String[] args) { TreeSet<Integer> evenNumbers = new TreeSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("TreeSet1: " + evenNumbers); TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("TreeSet2: " + numbers); numbers.addAll(evenNumbers); System.out.println("Union is: " + numbers); } }
输出:
1 2 3 TreeSet1: [2 , 4 ] TreeSet2: [1 , 2 , 3 ] Union is: [1 , 2 , 3 , 4 ]
Intersection 为了执行两个集合之间的交集,我们使用了retainAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.TreeSet;;class Main { public static void main (String[] args) { TreeSet<Integer> evenNumbers = new TreeSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("TreeSet1: " + evenNumbers); TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("TreeSet2: " + numbers); numbers.retainAll(evenNumbers); System.out.println("Intersection is: " + numbers); } }
输出:
1 2 3 TreeSet1: [2 , 4 ] TreeSet2: [1 , 2 , 3 ] Intersection is: [2 ]
Difference 要计算两组之间的差异,我们可以使用removeAll()
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;;class Main { public static void main (String[] args) { TreeSet<Integer> evenNumbers = new TreeSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("TreeSet1: " + evenNumbers); TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("TreeSet2: " + numbers); numbers.removeAll(evenNumbers); System.out.println("Difference is: " + numbers); } }
输出:
1 2 3 TreeSet1: [2 , 4 ] TreeSet2: [1 , 2 , 3 , 4 ] Difference is: [1 , 3 ]
Subset 要检查一个集合是否是另一个集合的子集,我们使用containsAll()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("TreeSet1: " + numbers); TreeSet<Integer> primeNumbers = new TreeSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("TreeSet2: " + primeNumbers); boolean result = numbers.containsAll(primeNumbers); System.out.println("Is TreeSet2 subset of TreeSet1? " + result); } }
输出:
1 2 3 TreeSet1: [1 , 2 , 3 , 4 ] TreeSet2: [2 , 3 ] Is TreeSet2 subset of TreeSet1? True
TreeSet中其它方法
Method
Description
clone()
创建TreeSet
的副本
contains()
在TreeSet中搜索指定的元素并返回布尔结果
isEmpty()
检查TreeSet
是否为空
size()
返回TreeSet的大小
clear()
从TreeSet中删除所有元素
TreeSet Vs. HashSet TreeSet和HashSet都实现Set接口。但是,它们之间存在一些差异。
与HashSet
不同,TreeSet
中的元素以某种顺序存储。这是因为TreeSet
也实现了SortedSet
接口。
TreeSet
提供了一些易于导航的方法。例如first()
,last()
,headSet()
,tailSet(
)等。这是因为TreeSet
还实现了NavigableSet
接口。
HashSet比TreeSet快,对于诸如add
,remove
,contains
和size
之类的基本操作。
TreeSet Comparator 我们可以自定义元素的顺序。为此,我们需要基于对树集中的哪些元素进行排序来创建自己的Comparator
类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import java.util.TreeSet;import java.util.Comparator;class Main { public static void main (String[] args) { TreeSet<String> animals = new TreeSet<>(new CustomComparator()); animals.add("Dog" ); animals.add("Zebra" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("TreeSet: " + animals); } public static class CustomComparator implements Comparator <String > { @Override public int compare (String animal1, String animal2) { int value = animal1.compareTo(animal2); if (value > 0 ) { return -1 ; } else if (value < 0 ) { return 1 ; } else { return 0 ; } } } }
输出:
1 TreeSet: [Zebra, Horse, Dog, Cat]
在上面的示例中,我们创建了一个树集,将CustomComparator
类作为参数传递。
CustomComparator
类实现Comparator
接口
然后,我们重写compare()
方法。现在,该方法将以相反的顺序对元素进行排序.
Java collection framework
的Iterator
接口允许我们访问集合的元素。它具有一个子接口ListIterator
。
所有Java
集合都包含iterator()
方法。此方法返回用于迭代集合元素的迭代器实例。
Iterator 中的方法 Iterator
接口提供了4种方法,可用于对集合元素执行各种操作。
hasNext()
- 如果集合中存在一个元素,则返回true
next()
- 返回集合的下一个元素
remove()
- 删除next()
返回的最后一个元素
forEachRemaining()
- 对集合的每个剩余元素执行指定的操作
例子🌰 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.ArrayList;import java.util.Iterator;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(3 ); numbers.add(2 ); System.out.println("ArrayList: " + numbers); Iterator<Integer> iterate = numbers.iterator(); int number = iterate.next(); System.out.println("Accessed Element: " + number); iterate.remove(); System.out.println("Removed Element: " + number); System.out.print("Updated ArrayList: " ); while (iterate.hasNext()) { iterate.forEachRemaining((value) -> System.out.print(value + ", " )); } } }
输出:
1 2 3 4 ArrayList: [1 , 3 , 2 ] Acessed Element: 1 Removed Element: 1 Updated ArrayList: 3 , 2 ,
在上面的示例中
1 iterate.forEachRemaining((value) -> System.put.print(value + ", " ));
在这里,我们将lambda表达式作为forEachRemaining()方法的参数传递。现在,该方法将打印数组列表中的所有其余元素。
Java collection framework
的ListIterator
接口提供了访问list
元素的功能.它是双向的。这意味着它允许我们在两个方向上迭代列表的元素。
List
接口提供了一个ListIterator()
方法,该方法返回ListIterator
接口的一个实例。
ListIterator中的方法
hasNext()
- 如果列表中存在一个元素,则返回true
next()
- 返回列表的下一个元素
nextIndex()
- 返回下个元素的索引.(调用next()
方法获取的元素)
previous()
- 返回列表的上一个元素
previousIndex()
- 返回列表的上一个元素索引(调用previousIndex()
方法获取的元素)
remove()
- 删除由next()
或previous()
返回的元素
set()
- 将next()
或previous()
返回的元素替换为指定的元素
例子🌰1 在下面的示例中,我们在数组列表中实现了ListIterator
接口的next()
,nextIndex()
和hasNext()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.ArrayList;import java.util.ListIterator;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(3 ); numbers.add(2 ); System.out.println("ArrayList: " + numbers); ListIterator<Integer> iterate = numbers.listIterator(); int number1 = iterate.next(); System.out.println("Next Element: " + number1); int index1 = iterate.nextIndex(); System.out.println("Position of Next Element: " + index1); System.out.println("Is there any next element? " + iterate.hasNext()); } }
输出:
1 2 3 4 ArrayList: [1 , 3 , 2 ] Next Element: 1 Position of Next Element: 1 Is there any next element? true
例子🌰2 在下面的示例中,我们在数组列表中实现了ListIterator
接口的previous()
和previousIndex()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.ArrayList;import java.util.ListIterator;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(3 ); numbers.add(2 ); System.out.println("ArrayList: " + numbers); ListIterator<Integer> iterate = numbers.listIterator(); iterate.next(); iterate.next(); int number1 = iterate.previous(); System.out.println("Previous Element: " + number1); int index1 = iterate.previousIndex(); System.out.println("Position of the Previous element: " + index1); } }
输出:
1 2 3 ArrayList: [1 , 3 , 2 ] Previous Element: 3 Position of the Previous Element: 0
在上面的示例中,最初,Iterator
的实例在1之前。由于在1之前没有元素,因此调用previous()
方法将引发异常。
然后,我们使用了next()
方法两次。现在,Iterator
实例将在3到2之间。因此,previous()方法返回3。
Java collection framework
提供了各种算法,可用于处理存储在数据结构中的元素。
Java中的算法是静态方法,可用于对集合执行各种操作。
由于算法可以用于各种集合,因此也称为通用算法。
使用sort()
排序 sort()方法用于对元素进行排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayList;import java.util.Collections;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(4 ); numbers.add(2 ); numbers.add(3 ); System.out.println("Unsorted ArrayList: " + numbers); Collections.sort(numbers); System.out.println("Sorted ArrayList: " + numbers); } }
输出:
1 2 Unsorted ArrayList: [4 , 2 , 3 ] Sorted ArrayList: [2 , 3 , 4 ]
在此,排序以自然顺序(升序)进行。但是,我们可以使用Comparator
接口自定义sort()
方法的排序顺序。
随机排序shuffle()
shuffle()
方法用于破坏数据结构中存在的任何种类的顺序,它与排序相反。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayList;import java.util.Collections;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("Sorted ArrayList: " + numbers); Collections.shuffle(numbers); System.out.println("ArrayList using shuffle: " + numbers); } }
输出:
1 2 Sorted ArrayList: [1 , 2 , 3 ] ArrayList using shuffle: [2 , 1 , 3 ]
当我们运行程序时,shuffle()
方法将返回随机输出。
常规数据操作 在Java中,collections framework
提供了可用于处理数据的不同方法。
reverse()
- 反转元素的顺序
fill()
- 用指定值替换集合中的每个元素
copy()
- 创建从指定源到目标的元素副本
swap()
- 交换集合中两个元素的位置
addAll()
- 将一个集合的所有元素添加到其他集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import java.util.Collections;import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); System.out.println("ArrayList1: " + numbers); Collections.reverse(numbers); System.out.println("Reversed ArrayList1: " + numbers); Collections.swap(numbers, 0 , 1 ); System.out.println("ArrayList1 using swap(): " + numbers); ArrayList<Integer> newNumbers = new ArrayList<>(); newNumbers.addAll(numbers); System.out.println("ArrayList2 using addAll(): " + newNumbers); Collections.fill(numbers, 0 ); System.out.println("ArrayList1 using fill(): " + numbers); Collections.copy(newNumbers, numbers); System.out.println("ArrayList2 using copy(): " + newNumbers); } }
输出:
1 2 3 4 5 6 ArrayList1: [1 , 2 ] Reversed ArrayList1: [2 , 1 ] ArrayList1 Using swap () : [1, 2] ArrayList2 using addALl () : [1, 2] ArrayList1 using fill () : [0, 0] ArrayList2 using copy () : [0, 0]
注意:在执行copy()方法时,两个列表的大小应相同。
使用binarySearch()
搜索 binarySearch()方法搜索指定的元素。它返回元素在指定集合中的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.Collections;import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); int pos = Collections.binarySearch(numbers, 3 ); System.out.println("The position of 3 is " + pos); } }
输出:
注意:应该在执行binarySearch()方法之前对集合进行排序。
Composition
frequency()
- 返回元素在集合中存在的次数
disjoint()
- 检查两个集合是否不相交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.Collections;import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(2 ); System.out.println("ArrayList1: " + numbers); int count = Collections.frequency(numbers, 2 ); System.out.println("Count of 2: " + count); ArrayList<Integer> newNumbers = new ArrayList<>(); newNumbers.add(5 ); newNumbers.add(6 ); System.out.println("ArrayList2: " + newNumbers); boolean value = Collections.disjoint(numbers, newNumbers); System.out.println("Two lists are disjoint: " + value); } }
输出:
1 2 3 4 ArrayList1: [1 , 2 , 3 , 2 ] Count of 2 : 2 ArrayList2: [5 , 6 ] Two lists are disjoint: true
寻找极限值 Java collections framework
的min()
和max()
方法分别用于查找最小和最大元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.Collections;import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); int min = Collections.min(numbers); System.out.println("Minimum Element: " + min); int max = Collections.max(numbers); System.out.println("Maximum Element: " + max); } }
输出:
1 2 Minimum Element: 1 Maximum Element: 3